What's Interface type in Go?
Golang Official website Language Specification document the concept of interface type is described below:
A interface type specifies a method set called its interface.
A variable of interface type can store a value of any type with a method set which is any superset of the interface.
Such a type is said to implement the interface. The value of an uninitialized variable of interface type is nil.
The Go language provides another type of data interface (interface), which defines all the common methods, only function signatures, no specific implementation code (similar to abstract functions in Java), and any other type that implements these methods as defined in the interface. Then it is said that this type implements (implement) the interface
The common definition of interfaces is as follows
/* 定义接口 */type interface_name interface { method_name1 [return_type] method_name2 [return_type] method_name3 [return_type] ... method_namen [return_type]}/* 定义xxx数据结构类型 */type struct_name xxx/* 实现接口方法 */func (struct_name_variable struct_name) method_name1() [return_type] { /* 方法实现 */} ...func (struct_name_variable struct_name) method_namen() [return_type] { /* 方法实现*/}
The above uses the type to declare an interface named Interface_name, and the interface type can be defined as a variable, such as
var name interface_name
The interface is a reference type in the Go language, so in the interface variable defined above, name is a pointer
We define the following instances according to the common definition of the interface above
//定义电话接口type Phone interface { call()}//自定义结构体type Nokia struct {}//实现接口方法func (nokia Nokia)call() { fmt.Println("I am Nokia, I can call you!")}func main() { var phone Phone phone = new(Nokia) phone.call()}
Call () is a phone interface defined by a method, and then by the Nokia implementation of the interface in this method, so Nokia implemented the phone interface.
Interface "polymorphic" attribute instances
A variable of type interface{}, which can be assigned using any type of value
func main() { var a interface{} = 123 var b interface{} = "abc" var c interface{} = 1.23 fmt.Println(a,b,c)}-----output----123 abc 1.23
In the standard packages that comes with the go language, there are many places that use interface to deal with unknown data types, such as our commonly used FMT packages to FMT. Println as an example, its function signature format is as follows
// Println formats using the default formats for its operands and writes to standard output.// Spaces are always added between operands and a newline is appended.// It returns the number of bytes written and any write error encountered.func Println(a ...interface{}) (n int, err error) { return Fprintln(os.Stdout, a...)}
The println function of the FMT package requires a variable-length parameter passed into the interface type, which requires the variable-length parameters passed in to implement the Stringer interface defined in the FMT package when implementing the underlying printing behavior.
The Stringer interface types are described below:
// Stringer is implemented by any value that has a String method,// which defines the ``native'' format for that value.// The String method is used to print values passed as an operand// to any format that accepts a string or to an unformatted printer// such as Print.type Stringer interface { String() string}
So, the custom type wants to call FMT. Printf () Does a formatted print, which is just a matter of implementing the Stringer interface.
Example: Custom Output Type format
Defines a map collection and loops out the elements of the map
type PersonInfo struct { ID string Name string address string}func main() { //创建集合 var myMap map[string] PersonInfo //初始化集合 myMap = make(map[string]PersonInfo) //向map中添加元素 myMap ["1"] = PersonInfo{"1","zhangsan","shanghai"} myMap ["2"] = PersonInfo{"2","wangwu","beijing"} myMap ["3"] = PersonInfo{"3","lisi","tianjin"} //循环输出 for num,person := range myMap{ fmt.Printf("%v: %v\n",num,person) }}----------output------------1: {1 zhangsan shanghai}2: {2 wangwu beijing}3: {3 lisi tianjin}
Now we want to customize the format of the output of the map collection, such as the output of the first element: 1: {1&zhangsan&shanghai}, so PersonInfo need to implement Stringer interface
//自定义类型需要实现Stringer接口func (pInfo PersonInfo)String()string { return fmt.Sprintf("%v&%v&%v",pInfo.ID,pInfo.Name,pInfo.address)}
The final custom formatted output is:
1: 1&zhangsan&shanghai2: 2&wangwu&beijing3: 3&lisi&tianjin
Interface embedding
The interface of the go language is very good for embedding, and the interface can be embedded in other interfaces, and the effect is just like adding a method embedded in the interface directly.
type HavingFoot interface { Foot()}type HavingEye interface { Eye()}type HuMan interface { HavingEye HavingFoot}
The human interface embeds the Havingfoot interface with the Havingeye interface, which is equivalent to the human interface that contains all the methods of the Havingfoot interface and the Havingeye interface. If you want to implement the human interface, define the Foot () and eye () methods.
Type guessing
If there are two types that implement the same interface, then both of these types of variables, a, B, can be assigned to the variable C of the interface type (similar to the upward pass in Java inheritance), and then the variable C of this interface type can be used to find whether the type variable A or B is assigned to it, and the common format is as follows:
value,ok := obj.(struct)
struct: Type A or B value to be guessed: return type variable A or b
OK: Query result obj: variable C for interface type
Type guessing instance
//定义电话接口type Phone interface { call()}//自定义结构体type Nokia struct {}type Iphone struct {}//实现接口方法func (nokia Nokia)call() { fmt.Println("I am Nokia, I can call you!")}func (iphone Iphone)call() { fmt.Println("I am Iphone, I can call you!")}func main() { //将两个子类赋值给接口 var phone1 Phone = Nokia{} var phone2 Phone = Iphone{} //判断phone1是不是Nokia赋值给它的 if values,ok := phone1.(Nokia);ok { values.call() } //判断phone2是不是Nokia赋值给它的 if values,ok := phone2.(Iphone);ok { values.call() }}
Recommended reading: https://studygolang.com/articles/2652