package main
import "fmt"
// 示例1。
// AnimalCategory 代表动物分类学中的基本分类法。
type AnimalCategory struct {
kingdom string // 界。
phylum string // 门。
class string // 纲。
order string // 目。
family string // 科。
genus string // 属。
species string // 种。
}
//这里绑定,这个String方法不需要任何参数声明,但需要有一个string类型的结果声明。我在调用fmt.Printf函数时,使用占位符%s和category值本身就可以打印出后者的字符串表示形式,而无需显式地调用它的String方法。
func (ac AnimalCategory) String() string {
return fmt.Sprintf("%s%s%s%s%s%s%s",
ac.kingdom, ac.phylum, ac.class, ac.order,
ac.family, ac.genus, ac.species)
}
// 示例2。
type Animal struct {
scientificName string // 学名。
AnimalCategory // 动物基本分类。这是一个嵌入字段
}
// 该方法会"屏蔽"掉嵌入字段中的同名方法。
// func (a Animal) String() string {
// return fmt.Sprintf("%s (category: %s)", //Sprintf输出格式化的字符串
// a.scientificName, a.AnimalCategory)
// }
// 示例3。
type Cat struct {
name string
Animal
}
// 该方法会"屏蔽"掉嵌入字段中的同名方法。
// func (cat Cat) String() string {
// return fmt.Sprintf("%s (category: %s, name: %q)",
// cat.scientificName, cat.Animal.AnimalCategory, cat.name)
// }
func main() {
// 示例1。species字段指定了字符串值"cat",fmt.Printf函数会自己去寻找它。此时的打印内容会是The animal category: cat。
category := AnimalCategory{species: "cat"}
fmt.Printf("The animal category: %s\n", category)
// 示例2。
animal := Animal{
scientificName: "American Shorthair",
AnimalCategory: category,
}
fmt.Printf("The animal: %s\n", animal)
// 示例3。
cat := Cat{
name: "little pig",
Animal: animal,
}
fmt.Printf("The cat: %s\n", cat)
}
go run demo29.go
The animal category: cat
The animal: cat
The cat: cat
Why here three cat print it?
Because: cat's string () Method: func (cat Cat) String () string string, and methods of Animal: func (a Animal) String () string is commented, the execution time of the script, when Example 2 and Example 3 call fmt.Printf () method, you can only use func (ac AnimalCategory) String () string method to print the seven fields. Without comment, the method behind the string will overwrite the previous string method, print the results change.
package main
import "fmt"
// 示例1。
// AnimalCategory 代表动物分类学中的基本分类法。
type AnimalCategory struct {
kingdom string // 界。
phylum string // 门。
class string // 纲。
order string // 目。
family string // 科。
genus string // 属。
species string // 种。
}
//这里绑定,这个String方法不需要任何参数声明,但需要有一个string类型的结果声明。我在调用fmt.Printf函数时,使用占位符%s和category值本身就可以打印出后者的字符串表示形式,而无需显式地调用它的String方法。
func (ac AnimalCategory) String() string {
return fmt.Sprintf("%s%s%s%s%s%s%s",
ac.kingdom, ac.phylum, ac.class, ac.order,
ac.family, ac.genus, ac.species)
}
// 示例2。
type Animal struct {
scientificName string // 学名。
AnimalCategory // 动物基本分类。这是一个嵌入字段
}
// 该方法会"屏蔽"掉嵌入字段中的同名方法。
func (a Animal) String() string {
return fmt.Sprintf("%s (category: %s)", //Sprintf输出格式化的字符串
a.scientificName, a.AnimalCategory)
}
// 示例3。
type Cat struct {
name string
Animal
}
// 该方法会"屏蔽"掉嵌入字段中的同名方法。
func (cat Cat) String() string {
return fmt.Sprintf("%s (category: %s, name: %q)",
cat.scientificName, cat.Animal.AnimalCategory, cat.name)
}
func main() {
// 示例1。species字段指定了字符串值"cat",fmt.Printf函数会自己去寻找它。此时的打印内容会是The animal category: cat。
category := AnimalCategory{species: "cat"}
fmt.Printf("The animal category: %s\n", category)
// 示例2。
//使用fmt.Printf函数和%s占位符试图打印animal的字符串表示形式,相当于调用animal的String方法。
//虽然我们还没有为Animal类型编写String方法,但这样做是没问题的。
//因为在这里,嵌入字段AnimalCategory的String方法会被当做animal的方法调用。
//那如果我也为Animal类型编写一个String方法呢?这里会调用哪一个呢?
//animal的String方法会被调用。这时,我们说,嵌入字段AnimalCategory的String方法被“屏蔽”了。注意,只要名称相同,无论这两个方法的签名是否一致,被嵌入类型的方法都会“屏蔽”掉嵌入字段的同名方法。
animal := Animal{
scientificName: "American Shorthair",
AnimalCategory: category,
}
fmt.Printf("The animal: %s\n", animal)
// 示例3。
cat := Cat{
name: "little pig",
Animal: animal,
}
fmt.Printf("The cat: %s\n", cat)
}
daixuandeMacBook-Pro:q0 daixuan$ go run demo29.go
The animal category: cat
The animal: American Shorthair (category: cat)
The cat: American Shorthair (category: cat, name: "little pig")
All methods associated with a data type, together constitute the set of methods of this type. In the same way as a collection method of the same name can not appear. And, if they belong to a type of structure, then the type name thereof in any field names can not be overlapped.
We can put a field structure types is considered one of its properties, or a data, and then attached to it as an extension of a method in which a capacity above or a data operation. The properties and their ability (or the data and operations) packaged together, object-oriented programming
I declared a structure type, called Animal. It has two fields. One is the string type of field scientificName, representing the scientific name of the animal. And that the structure of another type of field declaration only AnimalCategory, it is what I wrote in front of the name. What does it mean?
The question is: field declarations Animal types AnimalCategory represent?
Statement on behalf of the Animal field AnimalCategory a type of embedded fields . Go language specification, if type names in a field of only field without a field name, then it is embedded in a field, the field can also be called anonymously. We can type the name of this variable followed by ".", And then followed by the embedded field type of reference to the field. In other words, both the type name is the type of embedded fields.
Speaking of references embedded in the structure of the field, Animal types have a method called Category, it is so written:
func (a Animal) Category() string {
return a.AnimalCategory.String()}
Receiver type approach is that Category Animal, recipient name is a. In this method, I a.AnimalCategory to a selection by the expression of the embedded field, and then select the String methods of the field and call it.
Incidentally, the right of an identifier representing variables plus ".", Together with the field name or expression is called the method name selected expression that is used to indicate the selection of a field or variable method.