golang 数据类型
按数据类别有以下几种数据类型:
- 基础类型:如布尔类型(bool),数字类型(int,int64,uint32,float64,complex64…),字符串类型(string), 数组类型([4]int, [8]string
- 派生类型: 指针类型(Pointer),结构化类型(struct), Channel 类型, 函数类型(f),切片类型,接口类型(interface), Map 类型。
按存储方式也有两大类数据类型:
- 值类型,也叫基本数据类型:数值类型、bool、string、数组、struct 结构体
- 引用数据类型:指针、slice 切片、管道 chan、map、以及 interface
值类型:变量直接存储值。值类型的数据存储在栈内存空间中,栈在函数调f返回后,内存会被释放。
引用类型:变量存储的是一个地址,这个地址存储最终的值。引用数据类型的数据存储在堆内存空间中,通过 GC 回收。
基础类型为值传递
函数调用时申明的基础类型均为值传递,如int,string,数组等,数据传入函数后会重新copy一份,函数内的修改不会影响外面的变量,外部变量的修改也不会影响函数类的变量。
func main () {
myvar := [ 4 ] string {” test0 “, ” test1 “, ” test3 “, ” test4 “}
go Test (myvar)
for i := 1 ; i <= 2 ; i ++ {
myvar[i] = ” loop ” + strconv. Itoa (i)
fmt. Printf (” Main Addr[ %p ]=> %v \n “, & myvar, myvar)
time. Sleep (time.Second * 2 )
}
}
func Test (myVar [ 4 ] string ) {
for {
fmt. Printf (” Type[ %T ]=> %v \n “, myVar, myVar)
time. Sleep (time.Second * 1 )
}
}
struct传值或传引用
struct默认是值传递,只有申明为结构指针时才是引用传递,如通过修改如下程序可验证
type ConnFields struct {
Port int
Num int
}
// struct传引用
func main () {
myField := & ConnFields{ 5200 , 1 }
go Test (myField)
for i := 1 ; i <= 2 ; i ++ {
myField.Port += i
fmt. Printf (” Main Addr[ %p ]=> {port: %d , id: %d } \n “,
myField, myField.Port, myField.Num)
time. Sleep (time.Second * 2 )
}
}
func Test (myField *ConnFields) {
for {
fmt. Printf (” Func Addr[ %p ] ==>{port: %d , id: %d } \n “, myField, myField.Port, myField.Num)
time. Sleep (time.Second * 1 )
}
}
map类型
map类型是传引用
func main () {
myMap := make ( map [ int ] string )
myMap[ 0 ] = ” test0 ”
go Test (myMap)
for i := 1 ; i <= 2 ; i ++ {
myMap[i] = ” loop ” + strconv. Itoa (i)
fmt. Printf (” Main Addr[ %p ]=> %v \n “, myMap, myMap)
time. Sleep (time.Second * 2 )
}
}
func Test (myMap map [ int ] string ) {
for {
fmt. Printf (” Func Addr[ %p ]=> %v \n “, myMap, myMap)
time. Sleep (time.Second * 1 )
}
}
slice(切片)
切片调用时传递的是引用
func main () {
mySlice := [] string {” test0 “, ” test1 “, ” test3 “, ” test4 “}
go Test (mySlice)
for i := 1 ; i <= 2 ; i ++ {
mySlice[i] = ” loop ” + strconv. Itoa (i)
fmt. Printf (” Main Addr[ %p ]=> %v \n “, mySlice, mySlice)
time. Sleep (time.Second * 2 )
}
}
func Test (mySlice [] string ) {
for {
fmt. Printf (” Func Addr[ %p ]=> %v \n “, mySlice, mySlice)
time. Sleep (time.Second * 1 )
}
}
interface{}接口类型
当申明函数变量为interface{}类型时,具体是值传递还是引用传递依赖传入变量自身
如下面的测试代码,当传入参数为数组时是值传递,当传入参数是切片时为引用传递
func main () {
myvar := [ 4 ] string {” test0 “, ” test1 “, ” test3 “, ” test4 “}
go Test (myvar)
for i := 1 ; i <= 2 ; i ++ {
myvar[i] = ” loop ” + strconv. Itoa (i)
fmt. Printf (” Main Addr[ %p ]=> %v \n “, & myvar, myvar)
time. Sleep (time.Second * 2 )
}
}
func Test (myVar interface {}) {
for {
fmt. Printf (” Type[ %T ]=> %v \n “, myVar, myVar)
time. Sleep (time.Second * 1 )
}
}