golang方法(method)返回值提取结构体(struct)取不到地址的原因是,①返回值并没有保存到变量中,返回值本身只是临时保存在程序运行的堆栈的某个不确定位置,不能取地址;②实参取地址用的操作符是是&,而形参声明变量类型为指针,需要地址值用的才是*;③声明形参为指针的参数的实参只能为地址值。
故先把修改后的代码列出,修改要点是把“*NewPerson1().Speak()”改为“var b=NewPerson1()(&b).Speak()”,同时把“NewPerson2().Speak()”改成“var a=NewPerson2()(&a).Speak()”,代码列出如下:
package main
import "fmt"
type PersonA struct{
name string
}
func (p *PersonA) Speak () {
fmt.Println ( "person speak" ,p.name)
}
func (p PersonA) Walk ( ){
fmt . Println ( "person walk",p.name)}
func NewPerson1()(p PersonA){
return PersonA{"new Person1"}}
func NewPerson2()(p PersonA){
return PersonA{"new Person2"}}
func main () {
var a=NewPerson2 ()(&a).Speak ()
a .Walk ()
fmt. Println ("--------------------")
var b=NewPerson1 ()(&b).Speak ()
b.Walk ()}
go代码调试效果
关于指针变量的使用这一点go语言和其他有指针的程序语言如c语言是一样的,从来只有返回值为地址/指针,而从没有在赋值前给返回值取地址这种运算,类似的错误晚点再整理。
不一样的是,go语言更简单go语言函数可以使用结构体或者结构体的指针(pointer)以传递结构体参数,而且和c语言不一样的是,go语言没有区分结构体指针和结构体访问成员的运算符,go语言只有“.”适用于两种情况,而没有c语言为结构体指针专门准备的“->”运算符。
可以使用结构体指针,作为结构体的方法的参数以指代自身吗,
你在实例的构造函数中给该类的静态变量赋值,在生成实例之前是取不到值的。也就是说,你必须实现一个这个抽象类的子类,然后再生成一个子类的实例,这时候才会调用该抽象类的实例构造函数,才会给静态变量赋值。
1、反射可以在运行时 动态获取变量的各种信息 ,比如变量的类型、类别;
2、如果是结构体变量,还可以获取到结构体本身的信息(包括结构体的字段、方法);
3、通过反射,可以修改 变量的值 ,可以调用关联的方法;
4、使用反射,需要import " reflect ".
5、示意图:
1、不知道接口调用哪个函数,根据传入参数在运行时确定调用的具体接口,这种需要对函数或方法反射。
例如以下这种桥接模式:
示例第一个参数funcPtr以接口的形式传入函数指针,函数参数args以可变参数的形式传入,bridge函数中可以用反射来动态执行funcPtr函数。
1、reflect.TypeOf(变量名),获取变量的类型,返回reflect.Type类型。
2、reflect.ValueOf(变量名),获取变量的值,返回reflect.Value类型reflect.Value是一个结构体类型。
3、变量、interface{}和reflect.Value是可以互相转换的,这点在实际开发中,会经常使用到。
1、reflect.Value.Kind,获取变量的 类别(Kind) ,返回的是一个 常量 。在go语言文档中:
示例如下所示:
输出如下:
Kind的范畴要比Type大。比如有Student和Consumer两个结构体,他们的 Type 分别是 Student 和 Consumer ,但是它们的 Kind 都是 struct 。
2、Type是类型,Kind是类别,Type和Kind可能是相同的,也可能是不同的。
3、通过反射可以在让 变量 在 interface{} 和 Reflect.Value 之间相互转换,这点在前面画过示意图。
4、使用反射的方式来获取变量的值(并返回对应的类型),要求数据类型匹配,比如x是int,那么久应该使用reflect.Value(x).Int(),而不能使用其它的,否则报panic。
如果是x是float类型的话,也是要用reflect.Value(x).Float()。但是如果是struct类型的话,由于type并不确定,所以没有相应的方法,只能 断言。
5、通过反射的来修改变量,注意当使用SetXxx方法来设置需要通过对应的指针类型来完成,这样才能改变传入的变量的值,同时需要使用到reflect.Value.Elem()方法。
输出num=20,即成功使用反射来修改传进来变量的值。
6、reflect.Value.Elem()应该如何理解?