Golang 面向对象编程

Posted 知其黑、受其白

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Golang 面向对象编程相关的知识,希望对你有一定的参考价值。

阅读目录

Golang 面向对象编程1

1 struct 声明和定义

1、Go中面向对象是通过 struct 来实现的,struct 是用户自定义的类型。

type User struct 
	Username string
	Sex      string
	Age      int
	AvatarUrl string

注意:type 是用来定义一种类型。

struct 初始化方法 1

var user User
user.Age = 18
user.Username = "user01"
user.Sex = "男"
user.AvatarUrl = "http://my.com/xxx.png"

注意:使用变量名+‘.’+字段名访问结构体中的字段。

package main

import "fmt"

type User struct 
	Username  string
	Sex       string
	Age       int
	AvatarUrl string


func main() 
	var user User
	user.Age = 18
	user.Username = "user01"
	user.Sex = "男"
	user.AvatarUrl = "http://my.com/xxx.png"
	fmt.Printf("user.username=%s age=%d sex%s avatar=%s\\n", user.Username, user.Age, user.Sex, user.AvatarUrl)

PS E:\\TEXT\\test_go\\one> go run .\\test1.go
user.username=user01 age=18 sex男 avatar=http://my.com/xxx.png
PS E:\\TEXT\\test_go\\one>

struct 初始化方法 2

package main

import "fmt"

type User struct 
	Username  string
	Sex       string
	Age       int
	AvatarUrl string


func main() 
	// 注意也可以部分初始化
	var user User = User
		Username:  "user01",
		Sex:       "男",
		Age:       18,
		AvatarUrl: "http://my.com/xxx.png",
	
	fmt.Printf("user.username=%s age=%d sex%s avatar=%s\\n", user.Username, user.Age, user.Sex, user.AvatarUrl)

	// 更简单的写法
	user1 := User
		Username: "user01",
		// 未初始化的字段就是默认值空或零
		// Sex:       "男",
		// Age:       18,
		AvatarUrl: "http://my.com/xxx.png",
	
	fmt.Println(user1)


PS E:\\TEXT\\test_go\\one> go run .\\test1.go
user.username=user01 age=18 sex男 avatar=http://my.com/xxx.png
user01  0 http://my.com/xxx.png
PS E:\\TEXT\\test_go\\one>

未初始化的结构体:

var user3 User
fmt.Printf("user3=%#v\\n", user3)
PS E:\\TEXT\\test_go\\one> go run .\\test1.go
user3=main.UserUsername:"", Sex:"", Age:0, AvatarUrl:""
PS E:\\TEXT\\test_go\\one>

结构体类型指针

package main

import "fmt"

type User struct 
	Username  string
	Sex       string
	Age       int
	AvatarUrl string


func main() 
	// 结构体类型指针
	var user *User = &User
	fmt.Printf("%p %#v\\n", user, user)


PS E:\\TEXT\\test_go\\one> go run .\\test1.go
0xc000026080 &main.UserUsername:"", Sex:"", Age:0, AvatarUrl:""
PS E:\\TEXT\\test_go\\one>

注意:&User 和 new(User) 本质上是一样的,都是返回一个结构体的地址。

package main

import "fmt"

type User struct 
	Username  string
	Sex       string
	Age       int
	AvatarUrl string


func main() 
	// 结构体类型指针
	// var user *User = &User
	// fmt.Printf("%p %#v\\n", user, user)
	// 0xc000026080 &main.UserUsername:"", Sex:"", Age:0, AvatarUrl:""

	var user *User = &User
		Username:  "user01",
		Sex:       "男",
		AvatarUrl: "http://my.com/xxx.png",
	
	// 这种写法是 go 的语法糖
	user.Age = 18
	// 相当于 go 内部的这种写法
	(*user).Username = "user001"
	fmt.Printf("user01=%#v\\n", user)
	// user01=&main.UserUsername:"user001", Sex:"男", Age:18, AvatarUrl:"http://my.com/xxx.png"

	test()


func test() 
	var user1 *User = new(User)
	user1.Age = 18
	fmt.Println(user1)
	// &  18 

2 struct 的内存布局及构造函数

结构体内存布局:占用一段连续的内存空间。

package main

import "fmt"

type Test struct 
	A int32
	B int32
	C int32
	D int32


func main() 
	var t Test
	fmt.Printf("a addr:%p\\n", &t.A)
	fmt.Printf("b addr:%p\\n", &t.B)
	fmt.Printf("c addr:%p\\n", &t.C)
	fmt.Printf("d addr:%p\\n", &t.D)

一个字符占四个字节,地址是16进制所以打印出的结果是连续的。

PS E:\\TEXT\\test_go\\one> go run .\\test1.go
a addr:0xc00000e0d0
b addr:0xc00000e0d4
c addr:0xc00000e0d8
d addr:0xc00000e0dc
PS E:\\TEXT\\test_go\\one>

结构体没有构造函数,必要时需要自己实现

自定义包:E:\\TEXT\\test_go\\one\\user\\user.go

package user

type User struct 
	Username  string
	Sex       string
	Age       int
	AvatarUrl string

自定义执行文件:E:\\TEXT\\test_go\\one\\user_test\\test.go

package main

import (
	"fmt"
	"one/user"
)

func main() 
	// 使用第三方类型定义了一个变量
	var users user.User
	users.Age = 33
	fmt.Printf("user=%#v\\n", users)

PS E:\\TEXT\\test_go\\one\\user_test> go run .\\test.go
user=user.UserUsername:"", Sex:"", Age:33, AvatarUrl:""
PS E:\\TEXT\\test_go\\one\\user_test>

编写构造函数:

E:\\TEXT\\test_go\\one\\user\\user.go

package user

type User struct 
	Username  string
	Sex       string
	Age       int
	AvatarUrl string


// 构造函数
func NewUser(username string, sex string, age int, avatar string) *User 
	// 第一种方式
	// user := &User
	// 	Username:  username,
	// 	Sex:       sex,
	// 	Age:       age,
	// 	AvatarUrl: avatar,
	// 
	user := new(User)
	user.Username = username
	user.Sex = sex
	user.Age = age
	user.AvatarUrl = avatar
	return user

初始化构造函数:

E:\\TEXT\\test_go\\one\\user_test\\test.go

package main

import (
	"fmt"
	"one/user"
)

func main() 
	u := user.NewUser("user01", "女", 33, "xx.jpg")
	fmt.Printf("user=%#v\\n", u)

PS E:\\TEXT\\test_go\\one\\user_test> go run .\\test.go
user=&user.UserUsername:"user01", Sex:"女", Age:33, AvatarUrl:"xx.jpg"
PS E:\\TEXT\\test_go\\one\\user_test>

匿名字段和嵌套

匿名字段:即没有名字的字段。

注意:匿名字段默认采用类型名作为字段名。

package main

import "fmt"

type User struct 
	Username  string
	Sex       string
	Age       int
	AvatarUrl string
	int
	string


func main() 
	var user User
	user.Username = "user001"
	user.Sex = "nv"
	user.int = 100
	user.string = "hello"

	fmt.Printf("user=%#v\\n", user)

PS E:\\TEXT\\test_go\\one> go run .\\test1.go
user=main.UserUsername:"user001", Sex:"nv", Age:0, AvatarUrl:"", int:100, string:"hello"
PS E:\\TEXT\\test_go\\one>

3 匿名字段和 struct 嵌套

package main

import "fmt"

type Address struct 
	Province string
	City     string


type User struct 
	Username string
	Sex      string
	address  Address


func main() 
	user := &User
		Username: "user01",
		Sex:      "nv",
		address: Address
			Province: "beijing",
			City:     "beijing",
		,
	

	fmt.Printf("user=%#v\\n", user)

PS E:\\TEXT\\test_go\\one> go run .\\test1.go
user=&main.UserUsername:"user01", Sex:"nv", address:main.AddressProvince:"beijing", City:"beijing"
PS E:\\TEXT\\test_go\\one>

指针方式

package main

import "fmt"

type Address struct 
	Province string
	City     string


type User struct 
	Username string
	Sex      string
	address  *Address


func main() 
	user := &User
		Username: "user01",
		Sex:      "nv",
		address: &Address
			Province: "beijing",
			City:     "beijing",
		,
	

	fmt.Printf("user=%#v\\n", user)

匿名结构体

package main

import "fmt"

type Address struct 
	Province string
	City     string


type User struct 
	Username string
	Sex      string
	*Address


func main() 
	var user User
	user.Username = "user0011"
	user.Sex = "nv"

	// 第一种方式
	user.Address = &Address
		Province: "bj",
		City:     "chengshi",
	

	// 第二种方式
	user.Province = "上海"
	user.City = "shanghai"
	
	// user 结构体中没有city去匿名结构体找city
	fmt.Printf("user=%#v addr=%#v city:%s\\n", user, user.Address, user.City)

PS E:\\TEXT\\test_go\\one> go run .\\test1.go
user=main.UserUsername:"user0011", Sex:"nv", Address:(*main.Address)(0xc0000523c0) addr=&main.AddressProvince:"上海", City:"shanghai"
PS E:\\TEXT\\test_go\\one>

匿名结构体冲突解决

冲突指定字段的名字即可解决。

package main

import "fmt"

type Address struct 
	Province string
	City     string


type User struct 
	Username string
	Sex      string
	City     string
	*Address


func main() 
	var user User
	user.Username = "user001"
	user.Sex = "nv"
	user.City = "beijing"

	fmt.Printf("user=%#v\\n", user)

	user.Address = new(Address)
	user.Address.City = "上海"
	fmt.Printf("user=%#v city of address:%s\\n", user, user.Address.City)


PS E:\\TEXT\\test_go\\one> go run .\\test1.go
user=main.UserUsername:"user001", Sex:"nv", City:"beijing", Address:(*main.Address)(nil)
user=main.UserUsername:"user001", Sex:"nv", City:"beijing", Address:(*main.Address)(0xc0000523e0) city of address:上海
PS E:\\TEXT\\test_go\\one
package main

import "fmt"

type Address struct 
	Province   string
	City       string
	CreateTime string

type Email struct 
	Account    string
	CreateTime string


type User struct 
	Username string
	Sex      string
	City     string
	*Address
	*Email


func main() 
	var user User
	user.Username = "user001"
	user.Sex = "nv"
	user.City = "beijing"
	user.Address = new(Address)
	user.Email = new(Email)
	user.Address.City = "上海"
	user.Email.CreateTime = "email_createtime"
	fmt.Printf("user=%#v createtime:%s\\n", user, user.Email.CreateTime)

PS E:\\TEXT\\test_go\\one> go run .\\test1.go
user=main.UserUsername:"user001", Sex:"nv", City:"beijing", Address:(*main.Address)(0xc0001004b0), Email:(*main.Email)(0xc0000523c0) createtime:email_createtime
PS E:\\TEXT\\test_go\\one>

4 struct 与 tag 应用

字段可见性,大写表示可公开访问,小写表示私有。

tag 是结构体的元信息,可以在运行的时候通过反射机制读取出来

字段类型后面,以反引号括起来的 key-value 结构的字符串,多个tag已逗号隔开。

package main

import (
	"encoding/json"
	"fmt"
)

// 双引号表示 value
type User struct 
	Username   string `json:"username",db:"user_name"`
	Sex        string `json:"sex"`
	Age        int    `json:"age"`
	avatarUrl  string
	CreateTime string


func main() 
	user := &User
		Username:   "user001",
		Sex:        "女",
		Age:        33,
		avatarUrl:  "https://my.com/xx.png",
		CreateTime: "2022-30-51",
	
	// json 序列化后是json格式,返回的是字符切片
	data, _ := json.Marshal(user)
	fmt.Printf("json str:%s\\n", string(data))

PS E:\\TEXT\\test_go\\one> go run .\\test1.go
json str:"username":"user001","sex":"女","age":33,"CreateTime":"2022-30-51"
PS E:\\TEXT\\test_go\\one>

5 函数方式实现一个简单的学生管理系统

实现一个简单的学生管理系统,每个学生有分数、年级、性别、名字等字段,用户可以在控制台添加学生、修改学生信息、打印所有学生列表的功能。

E:\\TEXT\\test_go\\one\\test1.go

package main

import (
	"fmt"
	"one/student"
	"os"
)

var (
	AllStudents []*student.Student
)

func showMenu() 
	fmt.Println("1、add student")
	fmt.Println("2、modify student")
	fmt.Println("3、show all student")
	fmt.Println("4、exited\\n\\n")


func inputStudent() *student.Student 
	var (
		username string
		sex      int
		grade    string
		score    float32
	)
	fmt.Println("please input username:")
	fmt.Scanf("%s\\n", &username)

	fmt.Println("please input sex:[0|1]")
	fmt.Scanf("%d\\n", &sex)

	fmt.Println("please input grade:[0-6]")
	fmt.Scanf("%s\\n", &grade)

	fmt.Println("please input score:[0|100]")
	fmt.Scanf("%f\\n", &score)

	stu := student.NewStudent(username, sex, score, grade)
	return stu


func AddStudent() 
	stu := inputStudent()
	for index, v := range AllStudents 
		if v.Username == stu.Username 
			fmt.Printf("user %s success update\\n\\n", stu.Username)
			AllStudents[index] = stu
			return
		
	

	AllStudents = append(AllStudents, stu)
	fmt.Printf("user %s success insert\\n", stu.Username)


func ModifyStudent() 
	stu := inputStudent()
	for index, v := range AllStudents 
		if v.Username == stu.Username 
			AllStudents[index] = stu
			fmt.Printf("user %s success update\\n\\n", stu.Username)
			return
		
	
	fmt.Printf("user %s is not fund\\n", stu.Username)


func ShowAllStudent() 
	for _, v := range AllStudents 
		fmt.Printf("user:%s info:%#v\\n", v.Username, v)
	


func main() 
	for 
		showMenu()
		var sel int
		fmt.Scanf("%d\\n", &sel)

		switch sel 
		case 1:
			AddStudent()
		case 2:
			ModifyStudent()
		case 3:
			ShowAllStudent()
		case 4:
			os.Exit(0)
		
	

PS E:\\TEXT\\test_go\\one> go run .\\test1.go
1、add student
2、modify student
3、show all student
4、exited


1
please input username:
wgchen
please input sex:[0|1]
1
please input grade:[0-6]
5
please input score:[0|100]
99
user wgchen success insert
1、add student
2、modify student
3、show all student
4、exited


1
please input username:
xiaojun
please input sex:[0|1]
1
please input grade:[0-6]
1
please input score:[0|100]
88
user xiaojun success insert
1、add student
2、modify student
3、show all student
4、exited


1
please input username:
ycc
please input sex:[0|1]
0
please input grade:[0-6]
6
please input score:[0|100]
100
user ycc success insert
1、add student
2、modify student
3、show all student
4、exited


3
user:wgchen info:&student.StudentUsername:"wgchen", Score:99, Grade:"5", Sex:1
user:xiaojun info:&student.StudentUsername:"xiaojun", Score:88, Grade:"1", Sex:1
user:ycc info:&student.StudentUsername:"ycc", Score:100, Grade:"6", Sex:0
1、add student
2、modify student
3、show all student
4、exited


4
PS E:\\TEXT\\test_go\\one>

E:\\TEXT\\test_go\\one\\student\\student.go

package student

type Student struct 
	Username string
	Score    float32
	Grade    string
	Sex      int


func NewStudent(username string, sex int, score float32, grade string) (stu *Student) 
	stu = &Student
		Username: username,
		Sex:      sex,
		Score:    score,
		Grade:    grade,
	
	return

Golang 面向对象编程2

函数不属于任何类型,方法属于特定的类型。

1 方法的定义

Go的方法采用另外一种方式实现。

Go 的方法是在函数前面加上一个接受者,这样编译器就知道这个方法属于哪个类型了。

package main

import "fmt"

// struct 值类型
type People struct 
	Name    string
	Country string


func (p People) Print() 
	fmt.Printf("name=%s country=%s\\n", p.Name, p.Country)


func (p People) Set(name string, country string) 
	p.Name = name
	p.Country = country


func main() 
	// p1 值拷贝
	var p1 People = People
		Name:    "people01",
		Country: "china",
	
	p1.Print()
	// 这样是修改不了结构本身的值的,因为是值拷贝
	p1.Set("peple_set", "shanghai")

PS E:\\TEXT\\test_go\\one> go run .\\main.go
name=people01 country=china
PS E:\\TEXT\\test_go\\one>

可以为当前包内定义的任何类型增加方法。

package main

import "fmt"

type Integer int

func (i Integer) Print() 
	fmt.以上是关于Golang 面向对象编程的主要内容,如果未能解决你的问题,请参考以下文章

Golang 面向对象编程

(三十)golang--面向对象

面向对象之结构体1

Golang面向对象编程(下)

Golang-struct

Golang-面向对象编程三大特性-多态