Go 结构体(struct)实现接口(interface)以及赋值、强转

 1、如果一个结构体实现了interface中的所有方法,那么他们之间可以相互赋值,也可以相互强转

type Hobby interface {
	Sing()
}

type Chinese struct {
	Name string
}

func (c *Chinese) Sing() {
	fmt.Printf("%s am singing <<北京欢迎你!>> \n", c.Name)
}

type American struct {
	Name string
	Age  int
}

func (a American) Sing() {
	fmt.Printf("%s am singing <<are you ok !!!>> \n", a.Name)
}

func TestQz(t *testing.T) {
	var aa interface{}
	var c1 *Chinese
	c1 = &Chinese{Name: "小明"}
	//aa = b

	// c1实现了Hobby中的所有方法,所有可以作为形参传给给Hobby
	Avv(c1) // 小明 am singing <<北京欢迎你!>>

	// aa不能强转为Chinese类型,因为没有赋值
	v, ok := aa.(Chinese)
	if ok {
		fmt.Println("成功转换001:", v)
	} else {
		fmt.Println("失败001") // 失败001
	}

	a := &American{Name: "Jeke"}
	aa = a
	// a实现了Hobby中的所有方法,所有可以作为形参传给给Hobby
	Avv(a) //Jeke am singing <<are you ok !!!>>

	// aa可以成功强转American结构体类型
	v1, ok := aa.(*American)
	if ok {
		fmt.Println("成功转换0022:", v1) // 成功转换0022: &{Jeke 0}
	} else {
		fmt.Println("失败0022")
	}

	// aa不可以强转为struct{}类型
	v2, ok := aa.(*struct {
		Name string
		Age  int
	})
	if ok {
		fmt.Println("成功转换00333:", v2)
	} else {
		fmt.Println("失败00333") // 失败00333
	}

	// a可以赋值Hobby, Hobby可以强转a类型,
    // 注意:a为指针类型,Hobby只能强转a的指针类型,值类型不行
	var hobby Hobby
	hobby = a
	v3, ok := hobby.(*American)
	if ok {
		fmt.Println("成功转换004444:", v3) //成功转换004444: &{Jeke 0}
	} else {
		fmt.Println("失败004444")
	}
}

func Avv(a Hobby) {
	a.Sing()
}

 2、a赋值给interface类型的b,b只能强转成a的type类型,不能转化为其他类型以及Kind类型

(type类型:系统原生数据类型:如 int、string、bool、float32 等类型,以及使用 type 关键字定义的类型

(Kind类型:种类(Kind)指的是对象归属的品种,在 reflect 包中有如下定义:https://mp.csdn.net/mp_blog/creation/editor/119148976

package main

import (
	"fmt"
	"reflect"
	"testing"
)

type Age int

// 强制类型转换
func TestQb(t *testing.T) {
	var a interface{}

	var b Age
	b = 32
	a = b

	tt := reflect.TypeOf(b)
	fmt.Println("类型 Type:", tt.Name()) // 类型 Type: Age
	fmt.Println("种类 Kind:", tt.Kind()) // 种类 Kind: int

	// a可以转换成b的type类型(系统原生数据类型)
	v, ok := a.(Age)
	if ok {
		fmt.Println("转换成功001:", v) // 转换成功001: 32
	} else {
		fmt.Println("失败001")
	}

	// 但a不能转换成b的种类Kind类型
	v1, ok := a.(int)
	if ok {
		fmt.Println("转换成功0022", v1)
	} else {
		fmt.Println("失败0022") // 失败0022
	}

	// 但a更不能转换成其他类型
	v2, ok := a.(int64)
	if ok {
		fmt.Println("转换成功00333:", v2)
	} else {
		fmt.Println("失败00333") // 失败00333
	}

	v3, ok := a.(string)
	if ok {
		fmt.Println("转换成功004444:", v3)
	} else {
		fmt.Println("失败004444") // 失败004444
	}
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在 Go 中,结构体型是值型。当我们将一个结构体变量赋值给一个接口变量时,实际上传递的是这个结构体变量的副本。如果我们希望在接口变量中保存结构体变量的指针,我们需要将结构体变量的指针强制转换为接口变量的型。 例如: ``` package main import "fmt" type Person struct { Name string Age int } func main() { p := Person{Name: "Tom", Age: 18} var i interface{} = p // 将结构体变量赋值接口变量 fmt.Println(i) // 输出 {Tom 18} modify(i) fmt.Println(i) // 输出 {Tom 18},原始结构体变量并没有被修改 } func modify(i interface{}) { p := i.(Person) // 将接口变量转换为结构体变量 p.Name = "Jerry" p.Age = 20 } ``` 在上面的例子中,我们创建了一个 `Person` 结构体变量 `p`,然后将它赋值给一个接口变量 `i`。在函数 `modify` 中,我们将接口变量 `i` 转换为 `Person` 结构体变量,然后修改结构体变量的字段值。但是这个修改只是修改了副本的值,原始结构体变量并没有被修改,因此最终输出结果仍然为 `{Tom 18}`。 需要注意的是,如果我们将一个空结构体变量赋值接口变量,并试图在接口变量中保存结构体变量的指针,会导致运行时错误。这是因为空结构体变量的内存地址是 nil,无法进行指针转换。因此,在处理空结构体变量时,我们需要特别小心。 例如: ``` package main import "fmt" type Person struct { Name string Age int } func main() { var p *Person var i interface{} = p // 将空结构体变量赋值接口变量 fmt.Println(i) // 输出 <nil> modify(i) fmt.Println(i) // 输出 <nil> } func modify(i interface{}) { p := i.(*Person) // 运行时错误:panic: interface conversion: interface {} is nil, not *main.Person p.Name = "Jerry" p.Age = 20 } ``` 在上面的例子中,我们定义了一个空的 `Person` 结构体指针 `p`,然后将它赋值给一个接口变量 `i`。在函数 `modify` 中,我们试图将接口变量 `i` 转换为 `*Person` 型的指针,以便进行结构体变量的修改。但是由于 `p` 的值为 nil,试图进行指针转换会导致运行时错误。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

开心码农1号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值