Golang基础5-指针、结构体、方法、接口

指针

和c/c++类似,但是go语言中指针不能进行偏移和运算,安全指针

&(取地址) *(根据地址取值)

nil(空指针)

make和new之前对比:make用于初始化slice,map,channel这样的引用类型

而new用于类型的内存分配,分配的值为类型0值,返回该类型指针

结构体

值传递

没有继承,但是可以通过组合来支持面向对象特性。

结构体中可以包括结构体,但是不能包括本身

简单demo

package main

import "fmt"

type person struct {
    name string
    city string
    age  int8
}

func main() {
    //创建变量
    var p1 person
    p1.name = "pprof.cn"
    p1.city = "北京"
    p1.age = 18
    fmt.Printf("p1=%v\n", p1)  //p1={pprof.cn 北京 18}
    fmt.Printf("p1=%#v\n", p1) //p1=main.person{name:"pprof.cn", city:"北京", age:18}

    var p2 = new(person)
    p2.name = "小明"
    p2.city = "武汉"
    p2.age = 10
    fmt.Printf("p2=%v\n", p2)
    fmt.Printf("p2=%#v\n", p2)

    //匿名结构体
    var user struct {
        Name string
        Age  int
    }
    //user := struct{
    //    Name string
    //    Age  int
    //}
    user.Name = "pprof.cn"
    user.Age = 18
    fmt.Printf("%#v\n", user)
}

注意可见性,如果变量名首字母大写,在其他包可以访问(类似于public),否则只能在相同package中访问。

结构体的嵌套

对于Student中匿名嵌套的话,输出对应值,不需要s.p

package main

import "fmt"

type Person struct {
    name string
    age  int
}

// Student 结构体嵌套和匿名嵌套
type Student struct {
    p      Person
    school string
    score  int
}

func main() {
    s := Student{
        p:      Person{name: "张三", age: 18},
        school: "武汉大学",
        score:  100,
    }

    fmt.Println(s.p.name)
}

方法

    • 绑定对象实例,只能为当前包内命名类型定义方法

方法定义:

   func (recevier type) methodName(参数列表)(返回值列表){}

    参数和返回值可以省略
    • 参数recevier任意命名,若方法未曾使用可省略参数名
    • receive可以是T和*T类型。T不能是接口
    • 不支持方法重载
    • 可以使用value或pointer调用全部方法,编译器自动转换

简单demo

receive的类型T和*T之间对比

package main

import "fmt"

// 结构体
type User struct {
    Name  string
    Email string
}

// 假设T,产生副本不影响原变量
func (u User) Notify() {
    fmt.Printf("&u = %p\n", &u)
    fmt.Println("User 通知消息给", u.Name, " 邮箱为:", u.Email)
    u.Email = "Notify"
}

//如果是*T,传入指针,就会影响u1
//func (u *User) Notify() {
//    fmt.Printf("u = %p\n", u)
//    fmt.Println("User 通知消息给", u.Name, " 邮箱为:", u.Email)
//    u.Email = "Notify"
//}

func main() {
    u1 := User{"user1", "user1.com"}
    fmt.Printf("&u1 = %p\n", &u1)
    u1.Notify()
    //u2 := &u1
    fmt.Println(u1) //不影响u1变量
    fmt.Println("*********")
    u2 := &User{"user2", "user2.com"}
    fmt.Printf("u2 = %p\n", u2)

    u2.Notify()
    fmt.Println(u2)

}

func (u User) Notify() 方法时输出,传递副本因此地址不同,修改u不影响mian函数的对象值

func(u *User)Notify()传递指针,影响对象变量的值。

总结:方法就是与特定类型关联的函数,方便相当于c++当中class中的成员函数。

匿名字段demo

通过组合实现于override继承之后覆盖方法的效果。

// 结构体
type User struct {
    Name  string
    Email string
}

type Manager struct {
    User
    Stage string
}

// User的方法
func (u *User) ToString() string {
    return fmt.Sprintf("%s %s\n", u.Name, u.Email)
}

// Manager的方法
func (m *Manager) ToString() string {
    return fmt.Sprintf("%s %s %s\n", m.Name, m.Email, m.Stage)
}

func main() {
    m := Manager{User: User{"李四", "manage.cn"}, Stage: "经理"}
    fmt.Println(m.ToString())
    fmt.Println(m.User.ToString())
}

接口

参考链接:https://www.cnblogs.com/chenny7/p/4497969.html

go语言接口详解:Go 语言接口的原理 | Go 语言设计与实现

interface抽象类型,是一组method的集合,类似于c++中的纯虚函数,如果一个类/对实现了interface中的所有方法就实现了interface接口。通过interface也就是可以实现多态特性。

简单demo

package main

import "fmt"

type Human struct {
    name  string
    age   int
    phone string
}

type Student struct {
    Human  //匿名字段
    school string
    loan   float32
}

type Employee struct {
    Human   //匿名字段
    company string
    money   float32
}

// Human实现SayHi方法
func (h Human) SayHi() {
    fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}

// Human实现Sing方法
func (h Human) Sing(lyrics string) {
    fmt.Println("La la la la...", lyrics)
}

// Employee重载Human的SayHi方法
func (e Employee) SayHi() {
    fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
        e.company, e.phone)
}

//func (s Student) SayHi() {
//    fmt.Printf("Hi, I am %s, I study in %s. Loan is %f\n", s.name,
//        s.school, s.loan)
//}
//func (s Student) Sing(lyrics string) {
//    fmt.Println("student Sing")
//}

// Interface Men被Human,Student和Employee实现
// 因为这三个类型都实现了这两个方法
type Men interface {
    SayHi()
    Sing(lyrics string)
}

func main() {
    mike := Student{Human{"Mike", 25, "222-222-XXX"}, "MIT", 0.0}
    paul := Student{Human{"Paul", 26, "111-222-XXX"}, "Harvard", 100}
    sam := Employee{Human{"Sam", 36, "444-222-XXX"}, "Golang Inc.", 1000}
    tom := Employee{Human{"Tom", 37, "222-444-XXX"}, "Things Ltd.", 5000}

    //定义Men类型的变量i
    var i Men

    //i能存储Student
    i = mike
    fmt.Println("This is Mike, a Student:")
    i.SayHi()
    i.Sing("November rain")

    //i也能存储Employee
    i = tom
    fmt.Println("This is tom, an Employee:")
    i.SayHi()
    i.Sing("Born to be wild")

    //定义了slice Men
    fmt.Println("Let's use a slice of Men and see what happens")
    x := make([]Men, 3)
    //这三个都是不同类型的元素,但是他们实现了interface同一个接口
    x[0], x[1], x[2] = paul, sam, mike

    for _, value := range x {
        value.SayHi()
    }
}

通过调用接口相当于实现了多态。

可以继续实现嵌入接口。

空接口demo

空interface(interface{})不包含任何的method

所有的类型都实现了空interface

空接口可以存储任意类型

空interface对于描述起不到任何的作用(因为它不包含任何的method),但是空interface在我们需要存储任意类型的数值的时候相当有用,因为它可以存储任意类型的数值。它有点类似于C语言的void*类型。

    // 定义a为空接口,作为函数参数,或者与slice,map等增强灵活性
    var a interface{}
    var i int = 5
    s := "Hello world"
    // a可以存储任意类型的数值
    a = i
    a = s

interface{}可断言类型

空接口断言demo

package main

import "fmt"

type Human struct {
    Name string
    Age  int
}

type Student struct {
    Human
    School string
}

// 作为函数形参
func Show(a interface{}) {
    fmt.Printf("type of:%T value:%v\n", a, a)
}

//判断当前类型
func JustifyType(i interface{}) {
    switch v := i.(type) {
    case string:
        fmt.Println("当前传入为string:", v)
    case int:
        fmt.Println("当前传入为int:", v)
    case Student:
        fmt.Println("当前为Student类型", v)
    default:
        fmt.Println("暂未预料")
    }
}

func main() {
    i := "hello"
    Show(i)
    JustifyType(i)

    j := 10
    Show(j)
    JustifyType(j)

    Show(123)
    JustifyType(123)

    h := Human{"Human", 123}
    Show(h)
    JustifyType(h)

    k := Student{}
    Show(k)
    JustifyType(k)

}

相关推荐

  1. golang学习笔记——结构嵌套接口

    2024-04-27 19:30:02       32 阅读
  2. 初识GolangGolang 中的结构方法

    2024-04-27 19:30:02       38 阅读
  3. golang学习-结构

    2024-04-27 19:30:02       50 阅读
  4. golang结构接口方法实现与交互使用示例

    2024-04-27 19:30:02       32 阅读
  5. Golang 语法系列:结构

    2024-04-27 19:30:02       51 阅读
  6. 指针基础 - golang

    2024-04-27 19:30:02       41 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-27 19:30:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-27 19:30:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-27 19:30:02       82 阅读
  4. Python语言-面向对象

    2024-04-27 19:30:02       91 阅读

热门阅读

  1. 富格林:可信方针实现安全盈利

    2024-04-27 19:30:02       40 阅读
  2. vue中nextTick函数和react类似实现

    2024-04-27 19:30:02       43 阅读
  3. mysql binlog 中的位点生成逻辑是什么?

    2024-04-27 19:30:02       37 阅读
  4. vue中 key 的原理

    2024-04-27 19:30:02       31 阅读
  5. 路径筛选攻略:从列表中快速定位最大范围路径

    2024-04-27 19:30:02       29 阅读
  6. HTML表单和URL重写分别如何实现

    2024-04-27 19:30:02       31 阅读
  7. ubuntu Qt打包

    2024-04-27 19:30:02       35 阅读