go语法-结构体和接口

 

看go代码,非常考验对go语言的理解程度。觉得费解的地方,肯定是有不熟悉的语法。

 

 

3,接口与实现

type Error interface {
	Error() string
	Stacktrace() Error
	Trace(offset int, format string, args ...interface{}) Error
	Data() interface{}
}

 

type A struct {
  data  interface{}
  msgtraces []msgtraceItem
  stacktrace []uintptr
}
function newA(data interface{}) {
  return &A{
    data:  data
    msgtraces: nil
    stacktrace: nil
  }
}

func (a A) Error() string {
  return fmt.Sprintf("#{err}");
}

func (a A) Stacktrace() Error {
  return a; // 因为a是实现Error接口的结构体的实例
}

func (a A) Trace() Error {
  return a;
}

func (a A) Data() interface{} {
  return a.data;
}

  

 

3,接口

Go 语言的接口设计是非侵入式的,接口编写者无须知道接口被哪些类型实现。而接口实现者只需知道实现的是什么样子的接口,但无须指明实现哪一个接口。编译器知道最终编译时使用哪个类型实现哪个接口,或者接口应该由谁来实现。

a := PhoneConnecter{"PhoneConnecter"}
a.Connect()
Disconnect(a)

func Disconnect(usb USB) {
    if pc, ok := usb.(PhoneConnecter); ok {
        fmt.Println("Disconnect", pc.name)
        return
    }
    fmt.Println("Unknown device")
}
// 改造为空接口
func Disconnect(usb interface{}) {
    switch v := usb.(type)
    case PhoneConnecter
        fmt.Println("Disconnect", v.name)
    defult:
        fmt.Println("Unknown device")
}

接口转换可以降级。

比如 type struct TVConnect {

  name string

}

是不能强制转换为USB,因为没有实现USB。

 

 

1,结构体

结构体是不同数据类型的集合,聚合数据类型。数组是相同数据类型的集合。

go中没有类,继承,只保留了结构体及组合。

 

初始化的5种方法:

type struct Person {

  name string

  age int

  sex string

  address string

}

方法1:

var p1 Person

p2.name = ""

fmt.Printf(p2);

方法2:

p3: = Person{}

p3.name = ""

fmt.Printf(p3);

方法3://常用

p4: = Person{

  name: xx

}

fmt.Printf(p4);

方法4:

p5 := Person{"", } // 顺序不能写错

方法5:New // 指针类型

p1 := Person{"1", }

p2 := p1 // 深拷贝

p2.name = "2"

//结论是p1, p2两个空间。修改的时候两个互不干预。

var pp1 * Person

pp1 = &p1 // 浅拷贝

fmt.PrintLn(*pp1)

pp1.name = "3"

fmt.PrintLn(pp1) // &{}

fmt.PrintLn(p1) // {}

 

pp2 := new(Person) //指针类型

// (*pp2).name

pp2.name // 简写

 

结构体的指针

值类型:int,float,bool,string,array,struct

引用类型:slice,map,function,pointer

但常用指针: new (),不是nil,空指针,指向了新分配的类型的内存空间,里面存储的零值。

 

结构体是值类型:

p1 := Person{name:"", age:"", sex:"", address:"北京市"}

p2 := p1

p1.name = "newName"

p1变了,但p2没变。

默认是深copy,如果想浅copy,定义指针。

pp1 := &p1

pp1.name = "王五"; //这样原始数据p1就被修改了。

 

内置的pp2:=new(Person)

结构体是值类型,往往借助于指针来操作(通过new),new之后并不是nil,而是开辟了一段内存空间,存储零值。

 

newStruct是构造函数

结构体嵌套

package main
import "fmt"
type A struct {
    ax, ay int
}
type B struct {
    A
    bx, by float32
}
func main() {
    b := B{A{1, 2}, 3.0, 4.0}
    fmt.Println(b.ax, b.ay, b.bx, b.by) // 嵌入结构体的成员,可以通过外部结构体的实例直接访问。
    fmt.Println(b.A)
}

 

 匿名结构体,匿名字段(一个结构体的字段没有字段名)

匿名结构体类比匿名函数,平常不常用。

 s2:= struct {

name string

age int

} {

name:"李四"

age:"19"

}

 

匿名结构体字段

type Worker struct {

string

int

}

w2:=Work{"li", 32}

w2.string

w2.int

匿名字段类型不能重复,否则冲突。

还可以把另一个结构体作为匿名字段。

 

结构体嵌套

最初始的理解是对的。

type Book struct {

bookName string

price float64

}

type Student struct {

name string

age int

book Book

}

b1 := Book{}

b1.bookName = "西游记"

b1.price = 45.8

s1 := Student{}

s1.name = ""

s1.age = 

s1.book = b1;

s1.book.bookName

s1.book.price

也可以

s2:=Student{name:"", age: 19, book: Book{bookName:"", price:89.,7}}

 

实际结构体的嵌套需要定义指针,而不是值复制。

book :=  Book{bookName:"", price:89.,7}

s2:=Student{name:"", age: 19, book: &book}

 

go中的面向对象

用结构体嵌套来实现类的继承。

 

提升字段:子结构体是匿名字段的时候。可以直接使用子结构体的字段,不需要多点一次子结构体的名字。

注:代码里非常常用。

总结:嵌套分为两种情况:一种是模拟继承,is a子类是特殊的父类。可以直接访问子类的字段。

k另一种情况是:模拟面向对象的聚合关系,has a,一个类拥有另一个类。不能直接访问子类的字段。

 

posted @ 2020-11-13 19:08  走走停停走走  Views(184)  Comments(0Edit  收藏  举报