接口类型,Go语言学习函数+结构体+方法+接口
func(data int) { fmt.Println("hello", data) }(100)
将匿名函数分配给变量
可以为匿名函数体赋值,例如:
// 将匿名函数体保存到f()中 f := func(data int) { fmt.Println("hello", data) } // 使用f()调用 f(100)
匿名函数用作回调函数
使用时定义一个匿名函数,而不是先在被调用函数中声明,这才是callback的本质
// 遍历切片的每个元素,通过给定函数进行元素访问 func visit(list []int, f func(int)) { for _, v := range list { f(v) } } func main() { // 使用匿名函数打印切片内容 visit([]int{1, 2, 3, 4}, func(v int) { fmt.Println(v) }) }
可变参数 – 具有不确定数量参数的函数形式
所有参数都是可变参数:fmt.Println
func Println(a ...interface{}) (n int, err error) { return Fprintln(os.Stdout, a...) }
使用 fmt.Println 时,传入的值类型不受限制,例如:
fmt.Println(5, "hello", &struct{ a int }{1}, true)
当可变参数为 interface{} 类型时,可以传入任何类型的值
一些参数是可变的: fmt.Printf
fmt.Printf的第一个参数是参数列表,后面的参数是可变参数:
func Printf(format string, a ...interface{}) (n int, err error) { return Fprintf(os.Stdout, format, a...) } ------------------------------------------------------ fmt.Printf("pure stringn") fmt.Printf("value: %v %fn", true, math.Pi)
1.3 个闭包
闭包可以理解为在函数内部定义的函数。本质上,闭包是函数内部和函数外部之间的桥梁。简单来说,闭包=函数+引用环境
func main() { var f = add() fmt.Printf("f(10): %vn", f(10)) fmt.Printf("f(20): %vn", f(20)) // f(10): 10 // f(20): 30 } func add() func(int) int { var x int return func(y int) int { x += y return x } }
1.4 延迟语句
defer语句延迟后面的语句,defer语句以先进后出的方式执行(第一个defer语句最后执行,后面的defer语句先执行)。
特征:
采用:
处理运行时错误
Go语言的错误处理思路和设计包括以下特点:
错误接口定义格式
error 是 Go 系统声明的接口类型。代码如下:
type error interface { Error() string // 返回错误的具体描述. }
所有符合 Error() 字符串格式的接口都实现了 Error 接口。
定义错误
在 Go 语言中,使用 errors 包定义错误,格式如下:
var err = errors.New("this is an error")
因为错误字符串是比较固定的,所以一般在包作用域中声明,应该尽量减少直接使用errors.new在使用的时候返回。
恐慌 – 程序停止运行
手动触发停机
Go语言可以在程序中手动触发宕机,使程序崩溃,让开发者及时发现错误,减少可能的损失。
当 Go 语言程序宕机时,会将栈和 goroutine 信息输出到控制台,所以宕机时也可以很容易的知道错误的位置。
package main func main() { panic("crash") }
panic() 的参数可以是任何类型,
当 panic() 触发的崩溃发生时,panic() 之后的代码不会被执行,但是在 panic() 函数之前已经运行的 defer 语句在崩溃发生时仍然会生效。
1.5 崩溃恢复(recover)——防止程序崩溃
无论是Runtime层针对代码运行错误抛出的panic crash,还是主动触发的panic crash,都可以配合defer和recover实现错误捕获和恢复,让代码在crash后继续运行发生。
Go没有异常系统,其使用panic触发宕机与其他语言抛出异常类似,所以recover的宕机恢复机制对应try/catch机制。
恐慌与恢复的关系:
提示:虽然panic/recover可以模拟其他语言的异常机制接口类型,但不建议在编写普通函数时频繁使用该功能。
2. 结构
结构成员由一系列成员变量组成,也称为“字段”。
字段具有以下属性:
Go语言中没有“类”的概念,也不支持“类”的继承等面向对象的概念。
Go 语言中的结构体和“类”是复合结构体,但是 Go 语言中结构体的内联匹配接口比面向对象更具有可扩展性和灵活性。
Go 语言不仅认为结构可以有方法,而且每个自定义类型也可以有自己的方法。
2.1 给结构体定义和赋值
基本形式:
type Point struct { X int Y int } var p Point p.X = 10 p.Y = 20
结构体的定义只是对内存布局的描述接口类型,Go语言学习函数+结构体+方法+接口,只有当结构体实例化时,才会真正分配内存
创建一个指针类型的结构:
获取结构的地址并实例化它:
//使用结构体定义一个命令行指令(Command),指令中包含名称、变量关联和注释等 type Command struct { name string Var *int comment string } var version int = 1 cmd := &Command{} cmd.name = "version" cmd.Var = &version cmd.comment = "show version"
使用键值对填充结构:
type People struct { name string child *People } relation := &People{ name: "爷爷" child: &People{ name: "爸爸" child: &People{ name: "我" }, } }
3. 方法
Go 中的方法是作用于特定类型变量的函数。这种特殊类型的变量称为接收器。
当特定类型被理解为结构或“类”时,接收者的概念与其他语言中的 this 或 self 类似。
3.1 结构体方法
创建一个背包 Bag 结构体接口类型,Go语言学习函数+结构体+方法+接口,该结构体定义方法 insert 以将物品放入背包:
type Bag struct { items[] int } func (b *Bag) insert(itemid int) { b.items = append(b.items, itemid) } func main() { b := new(Bag) b.insert(1001) }
(b*Bag) 表示接收者,即 Insert 作用的对象实例。每种方法只能有一个接收器。
3.2 接收器
接收者是方法动作的目标
接收器可以按照接收器的类型来划分:
指针接收器
由于指针的特性,调用方法时,接收者指针的任何成员变量都会被修改,修改在方法结束后生效。
// 定义属性结构 type Property struct { value int } // 设置属性值方法 func (p *Property) setVal(val int) { p.value = val } // 获取属性值方法 func (p *Property) getVal() int { return p.value } func main() { p := new(Property) p.value = 123 fmt.Println(p.getVal()) p.setVal(666) fmt.Println(p.getVal()) }
非指针型接收器
当方法作用于非指针接收器时,Go 在代码运行时复制接收器的值。接收者的成员值可以在非指针接收者的方法中获取,但修改后无效。
type Point struct { x, y int } func (p Point) add(other Point) Point { return Point{p.x + other.x, p.y + other.y} } func main() { // 初始化点 p1 := Point{1, 1} p2 := Point{2, 2} res := p1.add(p2) fmt.Println(res) p3 := Point{3, 3} p4 := p1.add(p2).add(p3) fmt.Println(p4) }
指针接收器和非指针接收器的使用:
指针和非指针接收器的使用 在计算机中,小对象适合使用非指针接收器,因为它们的值复制速度更快。由于复制性能低,大对象适用于指针接收器。在接收者和参数之间传递时,不执行复制,而是传递指针。
4. 接口
接口是双方约定的合作协议。接口实现者不需要关心接口将如何使用接口类型,调用者也不需要关心接口的实现细节。接口是一种类型和一种抽象结构,它不公开其包含的数据的格式、类型和结构。
评论前必须登录!
注册