方法
go语言没有class, 但是可以给struct定义方法, 方法是带特殊接收者的函数,接受者在func关键字和方法名之间.比如:func (p Person) getName() string {},方法只是带接受者的函数,也可以写成这样func getName(p Person) string {}
package main
import "fmt"
type person struct {
name string
age int
}
func main() {
p := person{"zs", 22}
fmt.Println(p.getName()) //zs
p.changeAge1(44)
fmt.Println(p) //{zs 22}
p.changeAge(33)
fmt.Println(p) //{zs 33}
}
func (p person) getName() string {
return p.name
}
//指针接收者才能改变原始值, 否则会对原始值的副本进行操作
func (p *person) changeAge(age int) {
p.age = age
}
func (p person) changeAge1(age int) {
p.age = age
}
也可以给非结构体类型声明方法, 但是不能是内建类型,可以这样
type MyInt int定义一个类型.
以值为接收者的方法,既可以传值又可以传指针, 而函数必须传指定的类型.
接口
package main
import "fmt"
// 定义动物基本接口
type animals interface {
sound() string
}
type cat struct {
name string
age int
}
type dog struct {
name string
age int
}
// 实现接口里的所有方法
func (d dog) sound() string {
return d.name + "汪汪汪"
}
func (c cat) sound() string {
return c.name + "喵喵喵"
}
// 如果一个变量实现了某个接口, 就可以调用指定接口中的方法
func animalSound(a animals) {
fmt.Println(a)
fmt.Println(a.sound())
}
func main() {
c := cat{"小猫", 3}
d := &dog{"小狗", 3}
// dog和cat 都实现了animals接口, 所以可以作为实例作为animalSound的参数.
animalSound(c) //{小猫 3} 小猫喵喵喵
animalSound(d) //&{小狗 3} 小狗汪汪汪
}
空接口
空接口可以保存任何类型的值, 可以作为函数中未知类型的参数.
package main
import "fmt"
func main() {
var i interface{}
fmt.Printf("(%v, %T)\n", i, i) //(<nil>, <nil>)
i = 1
fmt.Printf("(%v, %T)\n", i, i) //(1, int)
i = "abc"
fmt.Printf("(%v, %T)\n", i, i) //(abc, string)
}
类型断言
v, ok := i.(T) 可以断言接口是不是保存了某个类型的值.
package main
import "fmt"
func main() {
var i interface{} = "gogo"
fmt.Println(i.(string)) //gogo
v, ok := i.(string)
fmt.Println(v, ok) // gogo true
f, ok := i.(float64)
fmt.Println(f, ok) //0 false
}
类型选择
package main
import "fmt"
func s(i interface{}) {
switch v := i.(type) {
case int:
fmt.Println(v, "int")
case string:
fmt.Println(v, "string")
default:
fmt.Println(v, "uknow")
}
}
func main() {
s(1) //1 int
s("a") //a string
s(false) //false uknow
}
错误处理
go里使用明确的返回值来传递错误信息, 通常放到最后一个返回的参数, 而且是error类型, 有两种创建错误的方法:
-
errors包的
errors.New("error message") -
自己实现Error()方法来自定义error类型.
package main
import (
"errors"
"fmt"
)
func f1(arg int) (int, error) {
if arg == 0 {
return -1, errors.New("can't work with 0")
}
return arg, nil
}
type argError struct {
arg int
what string
}
func (e *argError) Error() string {
return fmt.Sprintf("%d - %s", e.arg, e.what)
}
func f2(arg int) (int, error) {
if arg == 0 {
return -1, &argError{arg, "can't work with it"}
}
return arg, nil
}
func main() {
for i := range []int{0, 1} {
if r, e := f1(i); e != nil {
fmt.Println("f1 error:", e)
} else {
fmt.Println("f1 worked", r)
}
}
for i := range []int{0, 1} {
if r, e := f2(i); e != nil {
fmt.Println("f2 error:", e)
} else {
fmt.Println("f2 worked", r)
}
}
_, e := f2(0)
if a, ok := e.(*argError); ok {
fmt.Println(a.arg, a.what)
}
}
//f1 error: can't work with 0
//f1 worked 1
//f2 error: 0 - can't work with it
//f2 worked 1
//0 can't work with it
练习题:
学习更多Golang知识
不负春光 不负自己
戳“阅读原文”我们一起进步