大叔和身边一群大牛都无限看好 Go 语言,现在开始搞 Go 语言,过两年大概就是第一批吃螃蟹的人。
欢迎大家来到『Go 语言入门到精通』这个专栏,今天是专栏第 18 篇,大叔主要和大家分享一下 Go语言方法与接口相关的知识点
。
Go语言中的方法其实就是一个特殊函数, 只不过这个函数是和某种属性类型绑定在一起的而已
Go语言中的方法一般用于
将函数和结构体绑定在一起
, 让结构体除了能够保存数据外还能具备某些行为
将函数和数据类型绑定的格式
func (接收者 数据类型)方法名称(形参列表)(返回值列表){
方法体
}
package main
import 'fmt'
// 1.定义一个结构体
type Person struct {
name string
age int
}
// 2.定义一个函数, 并将这个函数和Person结构体绑定在一起
func (p Person)say() {
fmt.Println('my name is', p.name, 'my age is', p.age)
}
func main() {
// 3.创建一个结构体变量
per := Person{'lnj', 33}
// 4.利用结构体变量调用和结构体绑定的方法
// 调用时会自动将调用者(per)传递给方法的接收者(p)
// 所以可以在方法内部通过p方法结构体变量的属性
per.say()
}
package main
import 'fmt'
type Person struct {
name string
age int
}
// 定义一个方法
func (p Person)say() {
fmt.Println('say方法')
}
// 定义一个函数
func say() {
fmt.Println('say函数')
}
func main() {
p := Person{'lnj', 33}
fmt.Printf('%T\n', p.say) // func()
fmt.Printf('%T\n', say) // func()
// 定义一个保存没有形参没有返回值的函数类型变量
var fn func()
// 利用函数类型变量保存一个方法
fn = p.say
// 利用函数类型变量调用一个方法
fn()
// 利用函数类型变量保存一个函数
fn = say
// 利用函数类型变量调用一个函数
fn()
}
package main
import 'fmt'
type Person struct {
name string
age int
}
// 定义一个方法
func (p Person)say() {
fmt.Println('my name is', p.name, 'my age is', p.age)
}
// 定义一个函数
func test() {
fmt.Println('test')
}
func main() {
per := Person{'lnj', 33}
per.say() // 方法只能通过绑定类型的变量调用
//say() // 编译报错, 不能直接调用
test() // 编译通过, 可以直接调用
}
package main
import 'fmt'
type Person struct {
name string
age int
}
// 定义一个方法
func (p Person)say() {
fmt.Println('my name is', p.name, 'my age is', p.age)
}
// 定义一个函数
func test(p Person) {
fmt.Println('my name is', p.name, 'my age is', p.age)
}
func main() {
per := Person{'lnj', 33}
per.say() // my name is lnj my age is 33
test(per) // my name is lnj my age is 33
}
package main
import 'fmt'
type Person struct {
name string
age int
}
// 接收者是一个变量
func (p Person)setName(name string) {
p.name = name
}
// 接收者是一个指针
func (p *Person)setAge(age int) {
p.age = age
}
func main() {
per := Person{'lnj', 33}
fmt.Println(per) // {lnj 33}
// 值传递, 方法内部修改不会影响方法外部
per.setName('zs')
fmt.Println(per) // {lnj 33}
p := &per
// 地址传递, 方法内部修改会影响方法外部
(*p).setAge(18)
fmt.Println(per) // {lnj 18}
}
package main
import 'fmt'
type Person struct {
name string
age int
}
// 接收者是一个变量
func (p Person)setName(name string) {
p.name = name
}
// 接收者是一个指针
func (p *Person)setAge(age int) {
p.age = age
}
func main() {
per := Person{'lnj', 33}
// 方式一: 先拿到指针,然后再通过指针调用
p := &per
(*p).setAge(18)
fmt.Println(per) // {lnj 18}
// 方式二: 直接利用变量调用, 底层会自动获取变量地址传递给接收者
per.setAge(66)
fmt.Println(per) // {lnj 66}
}
type 接口名称 interface{
函数声明
}
package main
import 'fmt'
// 1.定义一个接口
type usber interface {
start()
stop()
}
type Computer struct {
name string
model string
}
// 2.实现接口中的所有方法
func (cm Computer)start() {
fmt.Println('启动电脑')
}
func (cm Computer)stop() {
fmt.Println('关闭电脑')
}
type Phone struct {
name string
model string
}
// 2.实现接口中的所有方法
func (p Phone)start() {
fmt.Println('启动手机')
}
func (p Phone)stop() {
fmt.Println('关闭手机')
}
// 3.使用接口定义的方法
func working(u usber) {
u.start()
u.stop()
}
func main() {
cm := Computer{'戴尔', 'F1234'}
working(cm) // 启动电脑 关闭电脑
p := Phone{'华为', 'M10'}
working(p) // 启动手机 关闭手机
}
type usber interface {
func start(){ // 错误
fmt.Println('启动')
}
func stop() { // 错误
fmt.Println('停止')
}
}
type usber interface {
name string // 错误
start()
stop()
}
该接口类型
接收 package main
import 'fmt'
// 1.定义一个接口
type usber interface {
start()
stop()
}
type Computer struct {
name string
model string
}
// 2.实现接口中的所有方法
func (cm Computer)start() {
fmt.Println('启动电脑')
}
func (cm Computer)stop() {
fmt.Println('关闭电脑')
}
// 2.只实现了接口中部分方法
type Phone struct {
name string
model string
}
func (p Phone)start() {
fmt.Println('启动手机')
}
func main() {
// 1.定义一个usber接口类型变量
var i usber
// 2.用usber接口类型变量接收Computer类型结构体
i = Computer{'戴尔', 'F1234'} // 实现了所有方法, 不会报错
// 3.用usber接口类型变量接收Phone类型结构体
//i = Phone{'华为', 'M10'} // 只实现了部分方法, 会报错
fmt.Println(i)
}
package main
import 'fmt'
type A interface {
fna()
}
type B interface {
fnb()
}
type C interface {
A // 嵌入A接口
B // 嵌入B接口
fnc()
}
type Person struct {}
func (p Person)fna() {
fmt.Println('实现A接口中的方法')
}
func (p Person)fnb() {
fmt.Println('实现B接口中的方法')
}
func (p Person)fnc() {
fmt.Println('实现C接口中的方法')
}
func main() {
p := Person{}
p.fna() // 实现A接口中的方法
p.fnb() // 实现B接口中的方法
p.fnc() // 实现C接口中的方法
}
type A interface {
A // 报错, 不能自己搞自己
}
type A interface {
fn()
}
type B interface {
fn()
}
type C interface {
A
B // 报错, A接口和B接口都有名称叫做fn的方法
fnc()
}
package main
import 'fmt'
type aer interface {
fna()
}
type ber interface {
aer
fnb()
}
// Person实现了超集接口所有方法
type Person struct {}
func (p Person)fna() {
fmt.Println('实现A接口中的方法')
}
func (p Person)fnb() {
fmt.Println('实现B接口中的方法')
}
// Student实现了子集接口所有方法
type Student struct { }
func (p Student)fna() {
fmt.Println('实现A接口中的方法')
}
func main() {
var i ber
// 子集接口变量不能转换为超集接口变量
//i = Student{}
fmt.Println(i)
var j aer
// 超集接口变量可以自动转换成子集接口变量,
j = Person{}
fmt.Println(j)
}
package main
import 'fmt'
func main() {
// 1.定义一个空接口类型变量
var i interface{}
// 2.用接口类型保存任意类型数据
i = 123
fmt.Println(i) // 123
i = 3.14
fmt.Println(i) // 3.14
i = 'lnj'
fmt.Println(i) // lnj
i = [3]int{1, 3, 5}
fmt.Println(i) // [1 3 5]
i = []int{2, 4, 6}
fmt.Println(i) // [2 4 6]
i = map[string]string{'name': 'lnj'}
fmt.Println(i) // map[name:lnj]
i = Computer{'戴尔', 'F1234'}
fmt.Println(i) // {戴尔 F1234}
}
package main
import 'fmt'
// 1.定义一个接口
type usber interface {
start()
stop()
}
// 2.自定义int类型
type integer int
// 2.实现接口中的所有方法
func (i integer)start() {
fmt.Println('int类型实现接口')
}
func (i integer)stop() {
fmt.Println('int类型实现接口')
}
func main() {
var i integer = 666
i.start() // int类型实现接口
i.stop() // int类型实现接口
}
package main
import 'fmt'
type studier interface {
read()
}
type Person struct {
name string
age int
}
func (p Person)read() {
fmt.Println(p.name, '正在学习')
}
func main() {
// 1.定义一个接口类型变量
var s studier
// 2.用接口类型变量接收实现了接口的结构体
s = Person{'lnj', 33}
s.name = 'zs' // 报错, 由于s是接口类型, 所以不能访问属性
fmt.Println(s)
}
package main
import 'fmt'
type studier interface {
read()
}
type Person struct {
name string
age int
}
func (p Person)read() {
fmt.Println(p.name, '正在学习')
}
func main() {
var s studier
s = Person{'lnj', 33}
s.name = 'zs' // 报错, 由于s是接口类型, 所以不能访问属性
// 2.定义一个结构体类型变量
//var p Person
// 不能用强制类型转换方式将接口类型转换为原始类型
//p = Person(s) // 报错
// 2.利用ok-idiom模式将接口类型还原为原始类型
// s.(Person)这种格式我们称之为: 类型断言
if p, ok := s.(Person); ok {
p.name = 'zs'
fmt.Println(p)
}
// 2.通过 type switch将接口类型还原为原始类型
// 注意: type switch不支持fallthrought
switch p := s.(type) {
case Person:
p.name = 'zs'
fmt.Println(p) // {zs 33}
default:
fmt.Println('不是Person类型')
}
}
package main
import 'fmt'
type studier interface {
read()
}
type Person struct {
name string
age int
}
func (p Person)read() {
fmt.Println(p.name, '正在学习')
}
func main() {
// 1.定义一个抽象接口类型
var i interface{}
i = Person{'lnj', 33}
// 不能调用read方法, 因为抽象接口中没有这个方法
//i.read()
// 2.利用ok-idiom模式将抽象接口转换为具体接口
if s, ok := i.(studier); ok{
// 可以调用read方法,因为studier中声明了这个方法,并且结构体中实现了这个方法
s.read() // lnj 正在学习
}
}
一个人走的太慢,一群人才能走的更远。
联系客服