Go 語言 結構體和方法

隱姓埋名4869發表於2022-04-20

@


1. 結構體別名定義

變數別名定義

package main

import "fmt"

type integer int

func main() {
	//型別別名定義
	var i integer = 1000
	fmt.Printf("值: %d, 型別: %T\n", i, i)

	var j int = 100
	j = int(i) 			//j和i不屬於同一型別,需要轉換
	fmt.Println(j)
}

//輸出結果如下
值: 1000, 型別: main.integer
1000

結構體別名定義

package main

import "fmt"

//建立結構體Student
type Student struct {
	Number int
}

//結構體定義別名
type Stu Student

func main() {
	//宣告Student型別結構體
	var a Student
	a = Student{30}

	//宣告Stu型別結構體
	var b Stu
	b = Stu{20}

	//強轉型別後才能進行賦值
	a = Student(b)
	fmt.Printf("a = %d,型別: %T\n", a, a)
	b = Stu(a)
	fmt.Printf("b = %d,型別: %T\n", b, b)
}


//輸出結果如下
a = {20},型別: main.Student
b = {20},型別: main.Stu

2. 工廠模式

  • Go 中所謂的工廠模式其實就是:
    包內一個不可直接例項的結構體(結構體名稱首字母小寫),包外不可直接例項,那麼為了解決這個問題,就寫一個包外可呼叫的函式,通過這個函式實現返回結構體物件。
package main

import "fmt"

type Student struct {
	Name string
	Age  int
}

func main() {
	//初始化
	stu1 := new(Student)
	fmt.Println(stu1)

	//工廠模式處理
	stu2 := NewStudent("張三", 18)
	fmt.Println(stu2)
}

//工廠模式
func NewStudent(name string, age int) *Student {
	return &Student{
		Name: name,
		Age:  age,
	}
}


//輸出結果如下
&{ 0}
&{張三 18}

總結:
make 用來建立mapslicechannel
new 用來建立值型別


3. Tag 原資訊

  • 在和其他語言進行對接互動時使用JSON格式,有些語言格式大小寫規範比較嚴格,為了使Go語言和其他語言對接資料傳輸,所以使用Tag原資訊進行解決

  • 通俗的來說就相當於是一個充電的轉介面

示例

package main

import (
	"encoding/json"
	"fmt"
)

type Student struct {
	Name  string
	Age   int
	Score float32
}

func main() {
	//初始化
	var stu = new(Student)
	stu.Name = "stu"
	stu.Age = 20
	stu.Score = 88

	//使用Json處理結構體,轉換成位元組陣列
	data, err := json.Marshal(stu)
	if err != nil {
		fmt.Println("錯誤提示:", err)
		return
	}
	fmt.Println(data)				//位元組陣列形式輸出
	fmt.Println(string(data))		//轉換成字串輸出
}


//輸出結果如下
[123 34 78 97 109 101 34 58 34 115 116 117 34 44 34 65 103 101 34 58 50 48 44 34 83 99 111 114 101 34 58 56 56 125]
{"Name":"stu","Age":20,"Score":88}

JSON格式化欄位名

package main

import (
	"encoding/json"
	"fmt"
)

type Student struct {
	//json打包時欄位名
	Name  string  `json:"stu_name"`
	Age   int     `json:"stu_age"`
	Score float32 `json:"stu_score"`
}

func main() {
	//初始化
	var stu = new(Student)
	stu.Name = "stu"
	stu.Age = 20
	stu.Score = 88

	//使用Json處理結構體,轉換成位元組陣列
	data, err := json.Marshal(stu)
	if err != nil {
		fmt.Println("錯誤提示:", err)
		return
	}
	fmt.Println(data)
	fmt.Println(string(data))
}


//輸出結果如下
[123 34 115 116 117 95 110 97 109 101 34 58 34 115 116 117 34 44 34 115 116 117 95 97 103 101 34 58 50 48 44 34 115 116 117 95 115 99 111 114 101 34 58 56 56 125]
{"stu_name":"stu","stu_age":20,"stu_score":88}

4. 匿名欄位

結構體中的欄位(屬性)沒有名稱,稱之為匿名欄位

示例

package main

import "fmt"

type Cart struct {
	name  string
	color string
}

type Train struct {
	//匿名欄位
	Cart //實現繼承
	int  //資料型別定義,僅能存在一次,兩個int則會衝突
}

func main() {
	//初始化賦值
	var t Train		
	t.name = "train"
	t.color = "red"
	t.int = 10		//直接呼叫資料型別賦值
	fmt.Println(t)
}

//輸出結果如下
{{train red} 10}

雙引用結構體,多繼承(繼承的兩個結構體中定義相同屬性)

package main

import "fmt"

//父結構體
type Cart struct {
	name  string
	color string
}

//父結構體
type Box struct {
	color string
}

//子結構體
type Train struct {
	//匿名欄位
	Cart //實現繼承
	Box
	int //資料型別定義,僅能存在一次,兩個int則會衝突
}

func main() {
	//初始化賦值
	var t Train
	t.name = "train"
	t.Cart.color = "red"
	t.Box.color = "blue"
	t.int = 10 //直接呼叫資料型別賦值
	fmt.Println(t)
}


//輸出結果如下
{{train red} {blue} 10}
package main

import "fmt"

//父結構體
type Cart struct {
	name  string
	color string
}

//父結構體
type Box struct {
	color string
}

//子結構體
type Train struct {
	//匿名欄位
	Cart //實現繼承
	Box
	int   //資料型別定義,僅能存在一次,兩個int則會衝突
	color string
}

func main() {
	//初始化賦值
	var t Train
	t.name = "train"
	t.Cart.color = "red" //Cart的屬性
	t.Box.color = "blue" //Box的屬性
	t.color = "yellow"   //train自身屬性
	t.int = 10           //直接呼叫資料型別賦值
	fmt.Println(t)
}

5. 方法

  • Go 中的方法是作用在特定型別的變數上,因此自定義型別,都可以有方法,而不僅僅是 struct
  • 語法格式如下
func (recevier type) methodName(引數列表)(返回值){}

recevier type     特定型別,如指標、別名,結構體 
methodName 	      方法名
  • 示例
package main

import "fmt"

//定義結構體
type Student struct {
	Name string
	Age  int
}

//定義方法
func (s Student) init(name string, age int) Student {
	s.Name = name
	s.Age = age
	return s
}

func main() {
	var stu Student
	s := stu.init("zhangsan", 18)
	fmt.Printf("s: %v\n", s)
}


//輸出結果
s: {zhangsan 18}

定義返回方法是否會把初始化的值給返回?

package main

import "fmt"

//定義結構體
type Student struct {
	Name  string
	Age   int
	Score float32
}

//初始化方法
func (s *Student) init(name string, age int, score float32) {
	s.Name = name
	s.Age = age
	s.Score = score
	fmt.Println("初始化完成")
}

//返回結構體
func (s *Student) get() Student {
	return *s
}

func main() {
	var stu Student
	//定義值
	stu.init("zhangsan", 18, 90)
	//返回值
	stu1 := stu.get()
	fmt.Println(stu1)
}

//輸出結果如下
初始化完成
{zhangsan 18 90}

傳統資料型別自定義方法,做資料型別轉換

package main

import "fmt"

//別名型別
type integer int

//傳統資料型別自定義方法
func (p integer) convert() string {
	return fmt.Sprintf("%d", p)
}

func main() {
	var i integer
	i = 100
	s := i.convert()
	fmt.Printf("型別:%T,值:%s\n", s, s)
}

//輸出結果如下
型別:string,值:100

指標傳入和值傳入的區別
值傳入不會對數值進行改變,指標傳入才可以改變數值

package main

import "fmt"

type integer int

//傳統資料型別自定義方法
func (p integer) convert() string {
	return fmt.Sprintf("%d", p)
}

//方法傳指標進行資料同步修改
func (p *integer) set(b integer) {
	*p = b
}

func main() {
	var i integer
	i = 100
	s := i.convert()
	fmt.Printf("型別: %T ,值: %s\n", s, s)
	fmt.Printf("型別: %T ,值: %d\n", i, i)
	i.set(200)
	fmt.Printf("i: %v\n", i)
}


//輸出結果如下
型別: string ,值: 100
型別: main.integer ,值: 100
i: 200

方法繼承,組合(匿名欄位是組合的特殊形式)

package main

import "fmt"

//父結構體
type Car struct {
	weight int
	name   string
}

//父方法
func (c *Car) Run() {
	fmt.Println("Running")
}

//子結構體Bike
type Bike struct {
	//組合(有名字)
	c     Car
	wheel int
}

//子結構體Train
type Train struct {
	//匿名
	Car
	wheel int
}

func main() {
	var bike Bike
	bike.c.name = "bike"
	bike.c.weight = 500
	bike.wheel = 2

	var train Train
	train.name = "train"
	train.weight = 140000
	train.wheel = 8

	fmt.Println(bike)
	//方法繼承,呼叫父結構體方法
	bike.c.Run()

	fmt.Println(train)
	//方法繼承
	train.Run()
}


//輸出結果如下
{{500 bike} 2}
Running
{{140000 train} 8}
Running
package main

import "fmt"

//父結構體
type Cart struct {
	weight int
	Color  string
}

//父方法
func (c Cart) Run() {
	fmt.Println("Running")
}

//子結構體train
type Train struct {
	Cart
	wheel int
}

//子結構體方法
func (t Train) String() string {
	str := fmt.Sprintf("color:[%s],weight:[%d],wheel:[%d]\n", t.Color, t.weight, t.wheel)
	return str
}

func main() {
	var train Train
	train.Color = "red"
	train.weight = 14000
	train.wheel = 8
	fmt.Println(train)
	train.Run()
	fmt.Printf("%s\n", train)
}

//輸出結果如下
color:[red],weight:[14000],wheel:[8]

Running
color:[red],weight:[14000],wheel:[8]

相關文章