method set
// Method Sets
// Sample program to show how to understand method sets.
package main
import "fmt"
// notifier is an interface that defines notification notifier是定义通知的接口。
// type behavior. 类型的行为。
type notifier interface {
notify()
}
// user defines a user in the program.
type user struct {
name string
email string
}
// notify implements the notifier interface with a pointer receiver. 通知用一个指针接收器实现notifier接口。
func (u *user) notifier() {
fmt.Printf("Sending User Email To %s<%s>\n",
u.name,
u.email)
}
func main() {
// Create a value of type User and send a notification. 创建类型用户的值并发送通知。
u := user{"Bill", "bill@email.com"}
// Values of type user do not implement the interface because pointer
// receivers don't belong to the method set of a value.
// 类型用户的值不实现该接口,因为指针。
// 接收器不属于值的方法集。
sendNotification(u)
// ./example1.go:36: cannot use u (type user) as type notifier in argument to sendNotification:
// user does not implement notifier (notify method has pointer receiver)
// /例二。go:36:不能使用u(类型用户)作为类型通知者在参数中发送通知:
//用户不实现通知器(通知方法有指针接收器)
}
// sendNotification accepts values that implement the notifier
// interface and sends notifications.
// sendNotification接受实现通知的值。
// 接口和发送通知。
func sendNotification(n notifier) {
n.notify()
}
package main
import "fmt"
// Sample program to show how polymorphic behavior with interfaces.
// 示例程序演示多态行为与接口的关系。
// reader is an interface that defines the act of reading data. 阅读器是定义读取数据行为的接口。
type reader interface {
read(b []byte) (int, error)
}
// file defines a system file.
type file struct {
name string
}
// read implements the reader interface for a file. // read实现文件的读取器接口。
func (file) read(b []byte) (int, error) {
s := "<rss><channel><title>Going Go Programming</title></channel></rss>"
copy(b, s)
return len(s), nil
}
// pipe defines a named pipe network connection. 管道定义了一个指定的管道网络连接。
type pipe struct {
name string
}
// read implements the reader interface for a network connection. read实现了网络连接的读取器接口
func (pipe) read(b []byte) (int, error) {
s := `{name: "bill", title: "developer"}`
copy(b, s)
return len(s), nil
}
func main() {
// Create two values one of type file and one of type pipe. 创建两个值一个类型文件和一个类型管道。
f := file{"data.json"}
p := pipe{"cfg_service"}
// Call the retrieve function for each concrete type. 为每个具体类型调用检索函数。
retrieve(f)
retrieve(p)
}
// retrieve can read any device and process the data. 检索可以读取任何设备并处理数据。
func retrieve(r reader) error {
data := make([]byte, 100)
len_, err := r.read(data)
if err != nil {
return err
}
fmt.Println(string(data[:len_]))
return nil
}
Address Of Value
// Sample program to show how you can't always get the address of a value.
//示例程序,以显示您不能总是得到一个值的地址。
package main
import "fmt"
// duration is a named type with a base type of int. // duration是一个命名类型,有一个基本类型的int类型。
type duration int
// notify implements the notifier interface. 通知实现notifier接口。
func (d *duration) notify() {
fmt.Println("Sending Notification in", *d)
}
func main() {
duration(42).notify()
// ./example3.go:18: cannot call pointer method on duration(42)
// ./example3.go:18: cannot take the address of duration(42)
}
Storage By Value
// Sample program to show how the concrete value assigned to
// the interface is what is stored inside the interface.
// 示例程序演示如何分配具体的值。
// 接口是存储在接口中的内容。
package main
import "fmt"
// printer displays information. 打印机显示信息。
type printer interface {
print()
}
// user defines a user in the program. 用户在程序中定义用户。
type user struct {
name string
}
// print displays the user's name. 打印显示用户的名字。
func (u user) print() {
fmt.Printf("User Name: %s\n", u.name)
}
func main() {
// Create values of type user and admin.
u := user{"Bill"}
// Add the values and pointers to the slice of
// printer interface values.
entities := []printer{
// Store a copy of the user value in the interface value.
u,
// Store a copy of the address of the user value in the interface value.
&u,
}
// Change the name field on the user value.
u.name = "Bill_CHG"
// Iterate over the slice of entities and call
// print against the copied interface value.
for _, e := range entities {
e.print()
}
// When we store a value, the interface value has its own
// copy of the value. Changes to the original value will
// not be seen.
// When we store a pointer, the interface value has its own
// copy of the address. Changes to the original value will
// be seen.
//当我们存储一个值时,接口值有它自己的值。
//价值的副本。更改原始值将。
// 不是。
//当我们存储一个指针时,接口值有它自己的值。
//地址的副本。更改原始值将。
/*
User Name: Bill
User Name: Bill_CHG
*/
}
// Sample program that explores how interface assignments work when
// values are stored inside the interface.
// 示例程序,探索接口分配如何工作。
// 值存储在接口中。
package main
import (
"fmt"
"unsafe"
)
// notifier provides support for notifying events. notifier为通知事件提供支持。
type notifier interface {
notify()
}
// user represents a user in the system.
type user struct {
name string
}
// notify implements the notifier interface.
func (u user) notify() {
fmt.Println("Alert", u.name)
}
func inspect(n *notifier, u *user) {
word := uintptr(unsafe.Pointer(n)) + uintptr(unsafe.Sizeof(&u))
value := (**user)(unsafe.Pointer(word))
fmt.Printf("Addr User: %p Word Value: %p Ptr Value: %v\n", u, *value, **value)
}
func main() {
// Create a notifier interface and concrete type value. 创建一个通知接口和具体类型值。
var n1 notifier
u := user{"bill"}
// Store a copy of the user value inside the notifier
// interface value. 在notifier接口值中存储用户值的副本。
n1 = u
// We see the interface has its own copy. 我们看到这个接口有它自己的副本。
// Addr User: 0x1040a120 Word Value: 0x10427f70 Ptr Value: {bill}
inspect(&n1, &u)
// Make a copy of the interface value.
n2 := n1
// We see the interface is sharing the same value stored in
// the n1 interface value.
// Addr User: 0x1040a120 Word Value: 0x10427f70 Ptr Value: {bill}
inspect(&n2, &u)
// Store a copy of the user address value inside the
// notifier interface value.
n1 = &u
// We see the interface is sharing the u variables value
// directly. There is no copy.
// Addr User: 0x1040a120 Word Value: 0x1040a120 Ptr Value: {bill}
inspect(&n1, &u)
}
/*
Addr User: 0xc042008230 Word Value: 0xc04202bf68 Ptr Value: {bill}
Addr User: 0xc042008230 Word Value: 0xc04202bf68 Ptr Value: {bill}
Addr User: 0xc042008230 Word Value: 0xc042008230 Ptr Value: {bill}
*/
练习
// Declare an interface named speaker with a method named speak. Declare a struct
// named english that represents a person who speaks english and declare a struct named
// chinese for someone who speaks chinese. Implement the speaker interface for each
// struct using a value receiver and these literal strings "Hello World" and "你好世界".
// Declare a variable of type speaker and assign the address of a value of type english
// and call the method. Do it again for a value of type chinese.
//使用名为speak的方法声明一个名为speaker的接口。声明一个结构体
//英文名,代表一个会说英语的人,并宣布一个结构名称。
//中国人说汉语。为每个用户实现speaker接口。
//结构体使用价值接收机和这些字符串“Hello World”和“你好世界”。
//声明一个类型的扬声器的变量,并分配一个英语的值的地址。
//并调用该方法。再做一遍,看看中文的价值。
// Add a new function named sayHello that accepts a value of type speaker.
// Implement that function to call the speak method on the interface value. Then create
// new values of each type and use the function.
//添加一个名为sayHello的新函数,该函数接受类型speaker的值。
//实现该函数调用接口值上的speak方法。然后创建
//每种类型的新值并使用该函数。
package main
import "fmt"
// speaker implements the voice of anyone.
type speaker interface {
speak()
}
// english represents an english speaking person.
type english struct{}
// speak implements the speaker interface using a
// value receiver.
func (english) speak() {
fmt.Println("Hello World")
}
// chinese represents a chinese speaking person.
type chinese struct{}
// speak implements the speaker interface using a
// pointer receiver.
func (*chinese) speak() {
fmt.Println("你好世界")
}
func main() {
// Declare a variable of the interface speaker type 声明一个接口扬声器类型的变量。
// set to its zero value.
var sp speaker
// Declare a variable of type english.
var e english
// Assign the english value to the speaker variable. 将英语值分配给speaker变量。
sp = e
// Call the speak method against the speaker variable.
sp.speak()
// Declare a variable of type chinese.
var c chinese
// Assign the chinese pointer to the speaker variable. 将中文指针指定给speaker变量。
sp = &c
// Call the speak method against the speaker variable.
sp.speak()
fmt.Println("============\n")
// Call the sayHello function with new values and pointers
// of english and chinese.
sayHello(english{})
sayHello(&english{})
sayHello(&chinese{})
}
// sayHello abstracts speaking functionality. sayHello抽象说话的功能。
func sayHello(sp speaker) {
sp.speak()
}
/*
Hello World
你好世界
============
Hello World
Hello World
你好世界
*/