Golang基础-Structs与Methods、Interfaces

Structs

  • 类型定义(type)相当于一种别名
  • 将struct定义为一种类型Car
  • NewCar函数return &Car{},返回指针
// car.go package elon // Car implements a remote controlled car. type Car struct { speed int batteryDrain int battery int distance int } // NewCar creates a new car with given specifications. func NewCar(speed, batteryDrain int) *Car { return &Car{ speed: speed, batteryDrain: batteryDrain, battery: 100, } }

struct的零值,When constructing the zero value for a struct type, all of the struct's fields will be set to their zero value:

type Person struct { Name string Age int } var myPerson Person fmt.Printf("Zero value Person: %#v", myPerson) // Output: Zero value Person: main.Person{Name:"", Age:0} // 给有数值的struct赋零值 myPerson = Person{}

Methods

  • 给Car类型绑定方法
  • 绑定方法到*Car,说明在指针上,函数内可以改变结构体的值;如果是Car,则是拷贝,不能改变原始变量的值。
package elon import "fmt" // TODO: define the 'Drive()' method func (car *Car) Drive() { if car.battery < car.batteryDrain { return } car.distance += car.speed car.battery -= car.batteryDrain } // TODO: define the 'DisplayDistance() string' method func (car *Car) DisplayDistance() string { return fmt.Sprintf("Driven %d meters", car.distance) } // TODO: define the 'DisplayBattery() string' method func (car *Car) DisplayBattery() string { return fmt.Sprintf("Battery at %d%%", car.battery) } // TODO: define the 'CanFinish(trackDistance int) bool' method func (car *Car) CanFinish(trackDistance int) bool { if (trackDistance+car.speed-1)/car.speed*car.batteryDrain > car.battery { return false } else { return true } }
  • 给新的自定义类型绑定方法不一定要求类型是struct,也可以是int等一般类型。

下面定义的DistanceUnit类型的原型是int。给两个自定义类型实现了Stringer interface,也就是自定义打印时输出什么。Stringer接口只有一个方法,String() string

type DistanceUnit int const ( Kilometer DistanceUnit = 0 Mile DistanceUnit = 1 ) type Distance struct { number float64 unit DistanceUnit } func (sc DistanceUnit) String() string { units := []string{"km", "mi"} return units[sc] } func (d Distance) String() string { return fmt.Sprintf("%v %v", d.number, d.unit) }

Interfaces

  • 定义了Greeter interface
  • 定义了Italian和Portuguese两种类型
  • 两种类型均实现了Greeter interface
  • SayHello参数有一个Greeter,一个接口,但是却可以传入实现了Greeter所有接口的类型的变量。
package airportrobot import "fmt" // Write your code here. // This exercise does not have tests for each individual task. // Try to solve all the tasks first before running the tests. type Greeter interface { LanguageName() string Greet(username string) string } func SayHello(username string, g Greeter) string { return fmt.Sprintf("I can speak %s: %s", g.LanguageName(), g.Greet(username)) } type Italian struct { } func (I Italian) LanguageName() string { return "Italian" } func (I Italian) Greet(username string) string { return fmt.Sprintf("Ciao %s!", username) } type Portuguese struct { } func (P Portuguese) LanguageName() string { return "Portuguese" } func (P Portuguese) Greet(username string) string { return fmt.Sprintf("Olá %s!", username) }

这里的Italian{}和Portuguese{}牵涉到golang中空结构体的一个作用,实现方法接收者。Italian和Portuguese都是struct{},一个没有任何字段的结构体,的别名,作为了两种新的类型,虽然本质是一样的,但这两种新类型将作为不同类型的存在。而这两种新类型,则各自实现了Greeter接口的两个函数。
Italian{}和Portuguese{}则都相当于struct{}{},struct{}是类型,后面的{}是初始化,最终出来的是一个空结构体。本质是空结构体,但实际上是Italian和Portuguese两种类型的两个值。

空结构体还有两个作用,将map的value作为空结构体实现set;实现空通道,常常会遇到通知型 channel,其不需要发送任何数据,只是用于协调 Goroutine 的运行,用于流转各类状态或是控制并发情况,由于该 channel 使用的是空结构体,因此也不会带来额外的内存开销。

fmt.Println(SayHello("mlg", Italian{})) fmt.Println(SayHello("glm", Portuguese{}))

为什么这里给type绑定方法用的不是指针?

For implementing the interface, it does not matter whether the method has a value or pointer receiver.

如果要改成指针形式的,则相应的调用函数也应改变。

type Portuguese struct { } func (P *Portuguese) LanguageName() string { return "Portuguese" } func (P *Portuguese) Greet(username string) string { return fmt.Sprintf("Olá %s!", username) } // 这里的调用传参也换成了指针(地址) fmt.Println(SayHello("glm", &Portuguese{}))

所以interface类型的参数可以传值也可以传指针?
经过实验,即使上面代码中Portuguese绑定的是值而不是指针,在调用SayHello时仍然可以传入&Portuguese{}。但是如果实现的方法绑定的是指针,则在调用SayHello时只能传入指针,不能传值。

Type Assertion

Interfaces in Go can introduce ambiguity about the underlying type. In fact, the empty interface can take any concrete value at all (including primitives). A type assertion allows us to extract the interface value's underlying concrete value using this syntax: interfaceVariable.(concreteType).
上面的SayHello函数的第二个参数是Greeter interface,但传入的值是却是其他类型的变量,可以使用Type Assertion来判断或转化为相应的类型。

func seeType(g Greeter) { switch g.(type) { case Italian: fmt.Println("Italian type") case Portuguese: fmt.Println("Portuguese type") } } seeType(Italian{}) // => Italian type seeType(Portuguese{}) // => Portuguese type var i interface{} = 12 // try: 12.3, true, int64(12), []int{}, map[string]int{} switch v := i.(type) { case int: fmt.Printf("the integer %d\n", v) case string: fmt.Printf("the string %s\n", v) default: fmt.Printf("type, %T, not handled explicitly: %#v\n", v, v) }

__EOF__

本文作者RoadWide
本文链接https://www.cnblogs.com/roadwide/p/17134853.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   roadwide  阅读(46)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2019-02-19 python使用print写文件
点击右上角即可分享
微信分享提示