Go基础教程04方法和接口

83 阅读3分钟

方法

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

练习题:

202209151729358.png

学习更多Golang知识

不负春光 不负自己

戳“阅读原文”我们一起进步