golang中接口的赋值问题
M1: 方法–>值接受者 --> 值对象 --> 接口定义success
M2: 方法–>值接受者 --> 指针对象 --> 接口定义success
M3: 方法–>指针接受者 --> 值对象 --> 不能赋值
M4: 方法–>指针接受者 --> 指针对象 --> 接口定义success
接口
在Go语言中接口(interface)是一种类型,一种抽象的类型。
interface是一组method的集合,是duck-type programming
的一种体现。接口做的事情就像是定义一个协议(规则),只要一台机器有洗衣服和甩干的功能,我就称它为洗衣机。不关心属性(数据),只关心行为(方法)。为了保护你的Go语言职业生涯,请牢记接口(interface)是一种类型。
接口的定义
type 接口类型名 interface{
方法名1( 参数列表1 ) 返回值列表1
方法名2( 参数列表2 ) 返回值列表2
…
}
- 接口名:使用type将接口定义为自定义的类型名。Go语言的接口在命名时,一般会在单词后面添加er,如有写操作的接口叫Writer,有字符串功能的接口叫Stringer等。接口名最好要能突出该接口的类型含义。
- 方法名:当方法名首字母是大写且这个接口类型名首字母也是大写时,这个方法可以被接口所在的包(package)之外的代码访问。
- 参数列表、返回值列表:参数列表和返回值列表中的参数变量名可以省略。
type Sender interface {
send(string, string) error
}
M1 案例
方法–>值接受者 --> 指针对象 --> 接口定义success
type Sender interface {
send(string, string) error
}
type EmailSender struct {
address string
port int
user string
password string
}
func (s EmailSender) send(to string, msg string) error {
fmt.Printf("send Email to %s, The msg is : %s \n", to, msg)
return nil
}
func main() {
var sender Sender
emailSender := EmailSender{"stmp.qq.com", 456, "ralph", "password"}
sender = emailSender
fmt.Printf("%T, %#v \n", sender, sender)
sender.send("ralphB", "testM1")
}
OUTPUT
[root@dev1 interface]# go run intf.go
main.EmailSender, main.EmailSender{address:"stmp.qq.com", port:456, user:"ralph", password:"password"}
send Email to ralphB, The msg is : testM1
M2 案例
方法–>值接受者 --> 指针对象 --> 接口定义success
type Sender interface {
send(string, string) error
}
type EmailSender struct {
address string
port int
user string
password string
}
func (s EmailSender) send(to string, msg string) error {
fmt.Printf("send Email to %s, The msg is : %s \n", to, msg)
return nil
}
func main() {
var sender Sender
per := &EmailSender{"stmp.qq.com", 456, "ralph", "password"}
sender = per
fmt.Printf("%T, %#v \n", sender, sender)
sender.send("ralphB", "testM2")
}
OUTPUT
[root@dev1 interface]# go run intf.go
*main.EmailSender, &main.EmailSender{address:"stmp.qq.com", port:456, user:"ralph", password:"password"}
send Email to ralphB, The msg is : testM2
M3 案例
方法–>指针接受者 --> 值对象 --> 不能赋值
type Sender interface {
send(string, string) error
}
type EmailSender struct {
address string
port int
user string
password string
}
func (s *EmailSender) send(to string, msg string) error {
fmt.Printf("send Email to %s, The msg is : %s \n", to, msg)
return nil
}
func main() {
var sender Sender
emailSender := EmailSender{"stmp.qq.com", 456, "ralph", "password"}
sender = emailSender
fmt.Printf("%T, %#v \n", sender, sender)
sender.send("ralphB", "testM3")
}
OUTPUT
[root@dev1 interface]# go run intf.go
# command-line-arguments
./intf2.go:25:11: cannot use emailSender (variable of type EmailSender) as type Sender in assignment:
EmailSender does not implement Sender (send method has pointer receiver)
M4 案例
方法–>指针接受者 --> 指针对象 --> 接口定义success
type Sender interface {
send(string, string) error
}
type EmailSender struct {
address string
port int
user string
password string
}
func (s *EmailSender) send(to string, msg string) error {
fmt.Printf("send Email to %s, The msg is : %s \n", to, msg)
return nil
}
func main() {
var sender Sender
per := &EmailSender{"stmp.qq.com", 456, "ralph", "password"}
sender = per
fmt.Printf("%T, %#v \n", sender, sender)
sender.send("ralphB", "testM4")
}
OUTPUT
[root@dev1 interface]# go run intf.go
*main.EmailSender, &main.EmailSender{address:"stmp.qq.com", port:456, user:"ralph", password:"password"}
send Email to ralphB, The msg is : testM4
总结
在golang中,定义了值接收者的方法,golang会默认创建它对应的指针接收者的方法。而定义了指针接收者的方法默认不会创建值接收者的方法,不过在结构体对象中定义了值对象是可以让指针接受者方法调用的,这个是因为golang自动帮我们做了取地址的语法糖
结构体对象 -> 值对象 -> 指针接受者方法 -> success!