当前位置: 首页 > 科技观察

如何理解Go中的可寻址和不可寻址?

时间:2023-03-14 21:24:14 科技观察

#1.什么是可寻址的?可以使用&运算符直接获取地址的对象是可寻址的。例如下面的例子funcmain(){name:="iswbm"fmt.Println(&name)//output:0xc000010200}程序运行时不会报错,说明变量名是可寻址的。但不能说字符串“iswbm”是可寻址的。“iswbm”是一个字符串,字符串是不可变的,不可寻址的,后面会介绍。在开始一一介绍之前,先说说指针可以寻址的结论:&Profile{}变量可以寻址:name:=Profile{}字面值不能寻址:Profile{}#2.什么是可寻址的?变量:&xfuncmain(){name:="iswbm"fmt.Println(&name)//输出:0xc000010200}指针:&*xtypeProfilestruct{Namestring}funcmain(){fmt.Println(unsafe.Pointer(&Profile{Name:"iswbm"}))//输出:0xc000108040}数组元素索引:&a[0]funcmain(){s:=[...]int{1,2,3}fmt.Println(&s[0])//输出:xc0000b4010}slicefuncmain(){fmt.Println([]int{1,2,3}[1:])}slice元素索引:&s[1]funcmain(){s:=make([]int,2,2)fmt.Println(&s[0])//output:xc0000b4010}combinedliterals:&struct{Xtype}{value}所有的组合文字都是不可寻址的,像下面的typeProfilestruct{Namestring}funcnew()Profile{returnProfile{name:"iswbm"}}funcmain(){fmt.Println(&new())//cannottaketheaddressofnew()}注意上面写法和这个写法的区别,下面的写法表示不同的意思,其中&不是操作取一个地址,而是一个指针来实例化一个结构。typeProfilestruct{Namestring}funcmain(){fmt.Println(&Profile{Name:"iswbm"})//ok}虽然组合字面量不可寻址,但是可以寻址组合字面量的字段属性(直接访问)typeProfilestruct{Namestring}funcnew()Profile{returnProfile{Name:"iswbm"}}funcmain(){fmt.Println(new().Name)}#3.哪些是不可寻址的?常量导入"fmt"constVERSION="1.0"funcmain(){fmt.Println(&VERSION)}stringfuncgetStr()string{return"iswbm"}funcmain(){fmt.Println(&getStr())//cannottaketheaddressofgetStr()}函数或方法funcgetStr()string{return"iswbm"}funcmain(){fmt.Println(&getStr)//cannottaketheaddressofgetStr}基本类型字面量分为基本类型字面量和复合类型字面量。原始类型文字是值的文本表示,不应该也不能是可寻址的。funcgetInt()int{return1024}funcmain(){fmt.Println(&getInt())//cannottaketheaddressofgetInt()}map中的元素字典比较特殊,可以从两个角度反向推导,假设字典的元素是可搜索的地址如果被使用会出现什么问题?如果字典的元素不存在,它将返回一个零值,零值是一个不可变对象。如果能解决,问题就大了。而如果字典的元素存在,考虑到Go中map实现中元素的地址是变化的,这意味着寻址的结果也是无意义的。基于这两点,Map中的元素是不可寻址的,符合常识。funcmain(){p:=map[string]string{"name":"iswbm",}fmt.Println(&p["name"])//cannottaketheaddressofp["name"]}明白这个,你应该就明白了为什么下面的代码报错~packagemainimport"fmt"typePersonstruct{NamestringEmailstring}funcmain(){m:=map[int]Person{1:Person{"Andy","1137291867@qq.com"},2:Person{"Tiny","qishuai231@gmail.com"},3:Person{"Jack","qs_edu2009@163.com"},}//编译错误:cannotassigntostructfieldm[1].Nameinmapm[1].Name="Scrapup“数组文字不可寻址。当你切片一个数组文字时,你实际上是在寻找内部元素的地址。下面的代码会报错funcmain(){fmt.Println([3]int{1,2,3}[1:])//invalidoperation[3]intliteral[1:](sliceofunaddressablevalue)}是不是很简单的?跟随明哥征服围棋知识的每一个角落!本文转载自微信公众号“Go编程时间”,可通过以下二维码关注。转载本文请联系围棋编程时间公众号。