- 使用接口给实现类的变量赋值,例一错误;例二正确。
- &与*的不同用法,前者是取地址,后者是引用
- 指针,或者说pointer是一串指向某个内存地址的字符串,所谓指向是指这串字符串的内容是内存地址的值
&
表示取地址,比如有一个变量a
那么&a
就是变量a
在内存中的地址;对于go,指针也是有类型的,比如如果a
是一个string
那么&a
是一个string
的指针类型:&string
- 对于
b := &a
这句代码:a,b是两个不同的变量,a是string
类型,b是&string
类型;打印b,会发现它是一串内存地址,而非a的值;所以为了拿到a的值,有个操作*
,用来取出指针对应内存地址里存的值,所以当打印*b
,会发现跟a一模一样
例一:
package main
import (
"fmt"
)
//声明一个接口
type IUser interface {
GetName() string
SetName(name string)
}
//声明一个User的结构去实现接口
type User struct {
Name string
}
func (a User) GetName() string {
return a.Name
}
func (a User) SetName(name string) {
a.Name = name
}
func main() {
var a IUser //声明a的类型是IUser类型
a = User{"李磊"} //给接口变量赋值
fmt.Println(a.GetName()) //输出:李磊
a.SetName("韩梅梅")
fmt.Println(a.GetName()) //输出:李磊,这里实际想输出的是"韩梅梅"
}
例二:
package main
import (
"fmt"
)
//声明一个接口
type IUser interface {
GetName() string
SetName(name string)
}
//声明一个User的结构去实现接口
type User struct {
Name string
}
func (a User) GetName() string {
return a.Name
}
//要改变对象的值必须用指针
func (b *User) SetName(name string) {
b.Name = name
}
func main() {
var a IUser //声明a的类型是IUser类型
a = &User{"李磊"} //a是指针了
fmt.Println(a.GetName()) //输出:李磊
a.SetName("韩梅梅")
fmt.Println(a.GetName()) //输出:韩梅梅
b := &a
// fmt.Println(b.GetName()) //这一步会报错:b.GetName undefined (type *IUser is pointer to interface, not interface)
c := *b //相当于c=a
c.SetName("小明")
fmt.Println(c.GetName()) //输出:小明
fmt.Println(a == c) //true
fmt.Println(&a == &c) //false
fmt.Println(&a) //变量a的内存地址
fmt.Println(&b) //变量b的内存地址
fmt.Println(&c) //变量c的内存地址
fmt.Println(*b) //解引用,输出b存储的数据(就是c) 输出:&{小明}
//fmt.Println(*a) //编译错误:invalid indirect of a (type IUser)
x := &User{"李磊"}
fmt.Println(*x) //{李磊}
fmt.Println(x) //&{李磊}
}
有疑问加站长微信联系(非本文作者)