9.interface

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
你好世界
*/

posted on 2018-03-17 17:38  cucy_to  阅读(150)  评论(0编辑  收藏  举报

导航