0
点赞
收藏
分享

微信扫一扫

Go 源码之互斥锁 Mutex

书坊尚 04-02 18:00 阅读 1

文章目录

1、面向对象

  • Go的结构体struct ⇒ Java的Class类
  • Go基于struct来实现OOP
  • 相比Java,Go去掉了方法重载、构造函数和析构函数、隐藏的this指针

定义个结构体,并创建结构体的实例:

package main
import "fmt"

//定义老师结构体,将老师中的各个属性  统一放入结构体中管理:
type Teacher struct{
        //变量名字大写外界可以访问这个属性
        Name string
        Age int
        School string
}

func main(){
        //创建老师结构体的实例、对象、变量:
        var t1 Teacher // var a int
        fmt.Println(t1) //在未赋值时默认值:{ 0 }
        t1.Name = "老师甲"
        t1.Age = 24
        t1.School = "XX大学"
        fmt.Println(t1)
        fmt.Println(t1.Age + 10)
}

2、结构体实例的创建

  • 方式一:直接创建

在这里插入图片描述

  • 方式二:使用{ },有点像Java的有参无参构造

在这里插入图片描述

  • 方式三:使用new关键字,返回一个指针类型,语法new(结构体类型名称)
package main
import "fmt"

//定义老师结构体,将老师中的各个属性  统一放入结构体中管理:
type Teacher struct{
        //变量名字大写外界可以访问这个属性
        Name string
        Age int
        School string
}

func main(){
        //创建老师结构体的实例、对象、变量:
        var t1 *Teacher = new(Teacher)
        //t1此时是指针,存了一个地址,应该给这个地址指向的对象的字段赋值
        (*t1).Name = "老师甲"
        (*t1).Age = 24
        //为了符合开发者习惯,go简化了赋值方式
        t1.School = "XX大学"  //go编译器底层对t1.School转化(*t1).School
        fmt.Println(t1)
}
  • 方式四:返回一个指针类型
package main
import "fmt"

//定义老师结构体,将老师中的各个属性  统一放入结构体中管理:
type Teacher struct{
        //变量名字大写外界可以访问这个属性
        Name string
        Age int
        School string
}

func main(){
        //创建老师结构体的实例、对象、变量:
        var t1 *Teacher = &Teacher{}
        //t1此时是指针,存了一个地址,应该给这个地址指向的对象的字段赋值
        (*t1).Name = "老师甲"
        (*t1).Age = 24
        //为了符合开发者习惯,go简化了赋值方式
        t1.School = "XX大学"  //go编译器底层对t1.School转化(*t1).School
        fmt.Println(t1)

		//也可这样
		var t2 *Teacher = &Teacher{"老师甲",22,"xx大学"}
		fmt.Println(t2)
}

最后,关于给结构体示例的字段赋值:

在这里插入图片描述

3、结构体之间的转换

  • 结构体和其它类型进行转换时需要有完全相同的字段(名字、个数和类型)
package main
import "fmt"
type Student struct {
        Age int
}
type Person struct {
        Age int
}
func main(){
        var s Student = Student{10}
        var p Person = Person{10}
        //注意
        s = Student(p)
        fmt.Println(s)
        fmt.Println(p)
}

type重新定义(相当于取别名),Go认为是新的数据类型,但是相互间可以强转

package main
import "fmt"
type Student struct {
        Age int
}

type Stu Student

func main(){
        var s1 Student = Student{19}
        var s2 Stu = Stu{19}
        //注意
        s1 = Student(s2)
        fmt.Println(s1)
        fmt.Println(s2)
}

4、方法

type A struct {
    Num int
}
func (a A) test() {
    fmt.Println(a.Num)
}

调用方法:

var a A
a.test()
  • func (a A) test()相当于A结构体有一个方法叫test
  • (a A) 体现方法test和结构体A绑定关系,即必须是A结构体的实例去调用

举例:

在这里插入图片描述

5、结构体值拷贝

值传递,即把值的副本进行了传递:

在这里插入图片描述

如果希望在方法中,改变结构体变量的值,可以通过结构体指针的方式来处理

在这里插入图片描述
内存图:

在这里插入图片描述
以上代码可直接简化,编译器底层自动加上 & 和 *

在这里插入图片描述

6、方法的注意点

  • 不仅仅是struct,比如int , float32等都可以有方法
package main
import "fmt"

//起别名
type integer int

//调这个方法必须是integer类型的实例
func (i integer) print(){
        i = 30
        fmt.Println("i = ",i)
}

//值传递改为指针类型
func (i *integer) change(){
        *i = 30
        fmt.Println("i = ",*i)
}


func main(){
        var i integer = 20
        i.print() 	//值传递,不会改变main方法栈中的i的值
        i.change()	//会改变main方法栈中的i的值
        fmt.Println(i)	//30
}
  • 同函数,方法名首字母小写,只能在本包访问,方法首字母大写,可以在本包和其它包访问

  • 如果一个类型实现了String()这个方法,那么fmt.Println输出这个类型的变量时,默认会调用这个类型中的String()进行输出,Java的toString

package main
import "fmt"
type Student struct{
        Name string
        Age int
}

func (s *Student) String() string{
        str := fmt.Sprintf("Name = %v , Age = %v",s.Name,s.Age)
        return str
}

func main(){
        stu := Student{
                Name : "丽丽",
                Age : 20,
        }
        //传入地址,如果绑定了String方法就会自动调用
        fmt.Println(&stu)
}

7、方法和函数的区别

  • 方法需要绑定指定数据类型,函数不用
  • 调用方式不同
//调用函数
函数名(实参列表)
//调用方法
变量.方法名(实参列表)

示例:

package main
import "fmt"
type Student struct{
        Name string
}
//定义方法:
func (s Student) test01(){
        fmt.Println(s.Name)
}
//定义函数:
func method01(s Student){
        fmt.Println(s.Name)
}
func main(){
        //调用函数:
        var s Student = Student{"丽丽"}
        method01(s)
        //方法调用:
        s.test01()
}

//输出结果
//丽丽
//丽丽
  • 对于函数来说,形参对应是什么就要传入什么
package main
import "fmt"
type Student struct{
        Name string
}
//定义函数:
func method01(s Student){
        fmt.Println(s.Name)
}
func method02(s *Student){
        fmt.Println((*s).Name)
}
func main(){
        var s Student = Student{"丽丽"}
        method01(s)
        //method01(&s)错误
        method02(&s)
        //method02(s)错误
}

  • 对于方法来说,接收者为值类型,可以传入指针类型,接受者为指针类型,可以传入值类型。
package main
import "fmt"
type Student struct{
        Name string
}
//定义方法:
func (s Student) test01(){
        fmt.Println(s.Name)
}
func (s *Student) test02(){
        fmt.Println((*s).Name)
}
func main(){
        var s Student = Student{"丽丽"}
        s.test01()
        (&s).test01()//虽然用指针类型调用,但是传递还是按照值传递的形式
        (&s).test02()
        s.test02()//等价
}

8、跨包创建结构体实例

在这里插入图片描述

在另一个包下创建实例:

在这里插入图片描述

注意上面能访问到,一者该结构体名称首字母大写,public,二者访问时带了包名.结构体名称。如果想要首字母小写实现访问 => 工厂模式

在这里插入图片描述
在另一个包下创建实例:

在这里插入图片描述

举报

相关推荐

0 条评论