主頁 > 後端開發 > Go語言中的結構體:靈活性與可擴展性的重要角色

Go語言中的結構體:靈活性與可擴展性的重要角色

2023-06-15 08:10:33 後端開發

1. 引言

結構體是Go語言中重要且靈活的概念之一,結構體的使用使得我們可以定義自己的資料型別,并將不同型別的欄位組合在一起,實作更靈活的資料結構,本文旨在深入介紹Go語言中的結構體,揭示其重要性和靈活性,并向讀者展示結構體支持的眾多特性,展示其強大之處,

2. 什么是結構體?

在Go語言中,結構體是一種自定義的資料型別,用于將不同型別的欄位組合在一起形成一個新的資料結構,結構體定義了一組欄位,每個欄位可以有不同的型別,這些欄位一起構成了結構體的實體,通過結構體,我們可以將相關的資料進行組織和管理,從而更方便地進行操作和傳遞,

結構體的定義使用關鍵字typestruct,以下是結構體的定義語法:

type 結構體名稱 struct {
    欄位1 型別1
    欄位2 型別2
    // 更多欄位...
}

在上述語法中,結構體名稱是我們為結構體型別起的名稱,可以根據實際情況進行命名,而結構體的欄位部分則列出了結構體包含的所有欄位,每個欄位都有一個欄位名和對應的欄位型別,下面我們給出一個結構體定義的示例:

type User struct {
    Name string
    Age  int
    Address string
}

述結構體定義了一個名為User的結構體型別,它包含了兩個欄位:NameAge,它們的型別分別為字串、整數,到此為止,我們完成了對結構體的基本介紹,能夠基于此創建出一種新的資料型別,

但是結構體的定義只是創建了一種新的資料型別,使用結構體需要創建其實體,Go語言中提供了幾種實體化方式,下面我們將對其進行詳細講述,

首先,可以使用結構體字面量直接初始化結構體變數,按照欄位順序給出對應的值,示例如下:

person := Person{"Alice", 25, "廣東深圳"}

其次可以使用指定欄位名的方式給出欄位的初始化值,這個時候可以忽略某些欄位,示例如下:

person := Person{Name: "Alice", Age: 25}

也可以使用new關鍵字創建一個指向結構體的指標,并回傳該指標,示例如下:

personPtr := new(Person)
personPtr.Name = "Alice"
personPtr.Age = 25

亦或者使用var關鍵字宣告結構體變數,然后分別給欄位賦值,示例如下:

var person Person
person.Name = "Alice"
person.Age = 25

以上是常見的結構體實體化和初始化方法,根據實際需要選擇合適的方式,無論使用哪種方式,都可以創建并初始化結構體的實體,以便后續使用和操作結構體的欄位,

到此為止,我們介紹了什么是結構體,其實結構體可以認為是一組不同型別欄位的組合,將其用來表示一個新的概念,其次我們也介紹了幾種實體化自定義結構體的方式,基于此我們對結構體有一個大概的了解,

3. 結構體支持哪些特性呢?

上面我們對結構體有了基本的了解,結構體可以組合一組不同型別的欄位,將其用來表示一個新的概念,但是結構體并不止步于此,其也支持定義方法,資料封裝等,通過這些特性,結構體在Go語言中具備了靈活性、可擴展性和可讀性,并且在面向物件編程、資料建模和代碼復用等方面發揮著重要作用,

3.1 結構體支持定義方法

結構體在Go語言中支持定義方法,方法是與結構體關聯的函式,這種特性使得我們可以將特定的行為和功能與結構體關聯起來,通過方法來操作結構體的資料,

下面是一個示例,演示了結構體支持定義方法的特性:

package main

import "fmt"

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

// 定義方法:列印個人資訊
func (p Person) PrintInfo() {
    fmt.Printf("Name: %s\n", p.Name)
    fmt.Printf("Age: %d\n", p.Age)
}

// 定義方法:修改年齡
func (p Person) UpdateAge(newAge int) {
    p.Age = newAge
}

func main() {
    // 創建一個 Person 結構體實體
    person := Person{Name: "John", Age: 30}
    // 呼叫結構體的方法:列印個人資訊
    person.PrintInfo() // Output: Name: John   Age: 30
    // 呼叫結構體的方法:修改年齡
    person.UpdateAge(35)
    // 再次呼叫方法,列印修改后的個人資訊
    person.PrintInfo() // Output: Name: John   Age: 35
}

在上述代碼中,我們定義了一個 Person 結構體,它包含了 NameAge 兩個欄位,然后,我們為結構體定義了兩個方法:PrintInfo()UpdateAge()

main() 函式中,我們創建了一個 Person 結構體實體 person,并通過該實體呼叫了兩個方法:PrintInfo()UpdateAge(),首先,我們呼叫 PrintInfo() 方法,列印出初始的個人資訊,然后,我們呼叫 UpdateAge() 方法,將年齡修改為 35,最后,我們再次呼叫 PrintInfo() 方法,列印修改后的個人資訊,

通過結構體定義方法,我們可以將與結構體相關的資料和操作封裝在一起,提高了代碼的可讀性和可維護性,方法能夠直接訪問結構體的欄位,并對其進行操作,使得代碼更加簡潔和清晰,

3.2 結構體支持資料可見性的設定

結構體在Go語言中支持資料可見性的特性,其通過首字母大小寫可以限制結構體欄位和方法的可見性,從而實作資訊的隱藏和封裝,

在結構體中,方法名或者欄位名,其首字母大寫,代表著對外是可見和可修改的;首字母小寫,則代表著對外為不可見的,如果想要讀取或者修改,只能通過對外暴露的介面來進行,通過這種方式,可以隱藏結構體的內部實作細節,同時確保對結構體資料的訪問和操作通過封裝的公開方法進行,提供了更好的安全性和封裝性,下面給出一個代碼的示例:

package main

import "fmt"

// 定義結構體
type Person struct {
    name string // 私有欄位
}

// 定義公開方法:設定姓名
func (p *Person) SetName(name string) {
    p.name = name
}

// 定義公開方法:獲取姓名
func (p *Person) GetName() string {
    return p.name
}

func main() {
    // 創建一個 Person 結構體實體
    person := Person{}
    // 這里將無法通過編譯
    // person.name = "hello eva"
    // 通過公開方法設定姓名和年齡
    person.SetName("John")
    // 通過公開方法獲取姓名和年齡并列印
    fmt.Println("Name:", person.GetName()) // Output: Name: John

}

上述代碼中,我們定義了一個 Person 結構體,它包含了 name 這個私有欄位,然后,我們為結構體定義了兩個公開方法GetName()SetName(),可以分別進行設定和讀取私有欄位name欄位的值,

如果直接通過結構體實體person去讀取name欄位,此時將無法通過編譯,通過這種方式,確保對結構體資料的訪問和操作通過封裝的公開方法進行,提供了更好的安全性和封裝性,

3.3 結構體能夠實作介面

介面定義了一組方法的契約,描述了這些方法的行為和簽名,

在Go語言中,介面是一種型別,由一組方法簽名組成,一個結構體可以實作該介面中的所有方法,此時可以認為其實作了該介面,從而可以以相同的方式被使用,這種特性提供了多型性,允許我們撰寫通用的代碼,適用于多種型別的結構體,以下是一個示例,演示了結構體如何實作一個介面:

package main

import "fmt"

// 定義介面
type Shape interface {
    Area() float64
    Perimeter() float64
}

// 定義矩形結構體
type Rectangle struct {
    Width  float64
    Height float64
}

// 實作介面方法:計算矩形的面積
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

// 實作介面方法:計算矩形的周長
func (r Rectangle) Perimeter() float64 {
    return 2 * (r.Width + r.Height)
}

func main() {
    // 創建一個矩形結構體實體
    rectangle := Rectangle{Width: 5, Height: 3}

    // 將矩形實體賦值給介面變數
    var shape Shape
    shape = rectangle

    // 通過介面呼叫方法,計算面積和周長
    area := shape.Area()
    perimeter := shape.Perimeter()

    fmt.Println("Area:", area)           // Output: Area: 15
    fmt.Println("Perimeter:", perimeter) // Output: Perimeter: 16
}

在上述代碼中,我們定義了一個介面 Shape,它包含了 Area()Perimeter() 兩個方法的簽名,然后,我們定義了一個矩形結構體 Rectangle,并為該結構體實作了介面 Shape 中定義的方法,

main() 函式中,我們創建了一個矩形結構體實體 rectangle,然后,我們將該矩形實體賦值給介面型別的變數 shape,因為矩形結構體實作了 Shape 介面,所以可以賦值給介面變數,

接著,我們通過介面變數 shape 呼叫了 Area()Perimeter() 方法,實際上是呼叫了矩形結構體上的對應方法,通過介面的呼叫方式,我們可以使用統一的方式對不同的結構體型別進行操作,無需關心具體的型別,

這種結構體實作介面的特性提供了多型性的支持,使得我們可以撰寫通用的代碼,適用于多種型別的結構體,它使得代碼更加靈活、可擴展,并且能夠更好地應對需求的變化,

3.4 結構體支持組合

結構體支持組合的特性,通過將其他結構體作為欄位嵌入,實作了代碼的復用和組合,這樣做可以使外部結構體直接訪問嵌入的結構體的欄位和方法,從而復用內部結構體的功能,

具體而言,通過在外部結構體中嵌入其他結構體作為匿名欄位,我們可以直接訪問內部結構體的欄位和方法,而無需顯式進行委托或包裝,下面是一個示例,演示了結構體支持組合的特性:

package main

import "fmt"

// 定義基礎結構體
type Person struct {
        Name string
        Age  int
}

// 定義擴展結構體,嵌入了基礎結構體
type Employee struct {
        Person     // 匿名欄位,嵌入 Person 結構體
        EmployeeID int
}

func main() {
        // 創建一個 Employee 結構體實體
        employee := Employee{
                Person: Person{
                        Name: "John",
                        Age:  30,
                },
                EmployeeID: 12345,
        }

        // 訪問內部結構體的欄位和方法
        fmt.Println("Name:", employee.Name) // Output: Name: John
        fmt.Println("Age:", employee.Age)   // Output: Age: 30
}

在上述代碼中,我們定義了兩個結構體:PersonEmployeeEmployee 結構體通過嵌入 Person 結構體作為匿名欄位實作了組合,

通過組合,Employee 結構體可以直接訪問嵌入欄位 Person 的欄位 NameAge,在 main() 函式中,我們創建了一個 Employee 結構體實體 employee,并可以直接訪問其內部結構體 Person 的欄位,

通過組合,我們可以復用其他結構體中的欄位和方法,避免重復撰寫相同的代碼,這樣可以提高代碼的復用性和可維護性,其次,組合也提供了一種靈活的方式來擴展結構體的功能,我們可以將介面型別作為欄位嵌入進去,在不同的場景下可以使用不同的實作,使得整個設計更加靈活,

結構體支持組合的特性,極大得增強了Go語言的表達力,使得我們可以更好地組織和管理代碼,實作更靈活和可擴展的程式設計,

3.5 結構體標簽支持

結構體支持設定標簽是 Go 語言提供的一個特性,標簽是以字串形式附加在結構體欄位上的元資料,用于提供額外的資訊和配置,這個特性是由 Go 語言的編譯器和相關庫支持的,同時遵循了 Go 語言定義的標準格式,

結構體標簽的格式為key:"value",可以包含一個或多個鍵值對,多個鍵值對之間使用空格分隔,標簽位于欄位宣告的反引號中,例如:

type Person struct {
        Name string `json:"name" db:"full_name"`
        Age  int    `json:"age" db:"age"`
}

Go語言中,結構體標簽已經在許多場景下起到了非常重要的作用,其中包含結構體的序列化和反序列化,資料庫映射,表單驗證等,下面我們簡單通過一個序列化的場景來簡單說明,更詳細的內容后續再講述,

type Person struct {
        Name string `json:"name"`
        Age  int    `json:"age"`
}

func main() {
        p := Person{Name: "John Doe", Age: 30}
        data, _ := json.Marshal(p)
        fmt.Println(string(data)) // Output: {"name":"John Doe","age":30}
}

在上述示例中,通過設定欄位的 json 標簽,我們可以指定 JSON 序列化時的欄位名稱,使得生成的 JSON 字串符合預期的格式,

這里,結構體標簽的設定可以提供更多的元資料和配置資訊,使得代碼更具可讀性、可維護性和靈活性,同時,標簽的決議和應用是在運行時進行的,使得我們可以在撰寫代碼時靈活配置和調整結構體欄位的行為,而無需修改代碼本身,這提供了更大的靈活性和便利性,

3.6 特性總結

在Go語言中,結構體是一種強大而靈活的資料型別,其支持方法的定義,也能夠實作介面,組合以及對可見性的設定,

這些特性的結合使得Go語言中的結構體非常強大和靈活,用戶可以使用結構體定義自己的資料型別,并為其定義方法和行為,同時,結構體可以與介面一起使用,實作多型性和代碼復用,結構體的組合和可見性設定提供了更高級別的抽象和封裝能力,使代碼更具可擴展性和可維護性,

同時結構體也定義了一套標簽規則,能夠使用標簽為欄位添加元資料,這增強了代碼的功能和表現力,在注釋、序列化、校驗和映射等方面,提高了代碼的可擴展性和可復用性,

4. 總結

在這篇文章中,我們首先從結構體的定義入手,明確了如何定義結構體,并介紹了結構體的四種實體化方式,通過這些基礎知識,我們對結構體有了一個基本的了解,

接下來,我們詳細討論了結構體支持的幾個重要特性,我們介紹了結構體支持定義方法的能力,使得我們可以為結構體添加自定義的行為,我們還了解了如何對結構體支持對資料可見性的設定,通過訪問控制來保護資料的安全性,我們還介紹了結構體能夠對介面進行實作,使得結構體可以滿足介面的要求,實作更靈活的代碼組織和抽象,最后我們還講述了結構體支持組合的特性,允許我們將多個結構體組合成一個更大的結構體,實作代碼的復用和組合性,

綜上所述,本文全面介紹了結構體的定義和實體化方式,并詳細講解了結構體支持的各種特性,基于以上內容,完成了對Go語言結構體的介紹,希望對你有所幫助,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/555186.html

標籤:其他

上一篇:【python基礎】函式-初識函式

下一篇:返回列表

標籤雲
其他(160990) Python(38230) JavaScript(25495) Java(18240) C(15237) 區塊鏈(8270) C#(7972) AI(7469) 爪哇(7425) MySQL(7251) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5875) 数组(5741) R(5409) Linux(5347) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4593) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2435) ASP.NET(2404) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1984) 功能(1967) HtmlCss(1966) Web開發(1951) C++(1940) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1881) .NETCore(1863) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Go語言中的結構體:靈活性與可擴展性的重要角色

    # 1. 引言 結構體是Go語言中重要且靈活的概念之一。結構體的使用使得我們可以定義自己的資料型別,并將不同型別的欄位組合在一起,實作更靈活的資料結構。本文旨在深入介紹Go語言中的結構體,揭示其重要性和靈活性,并向讀者展示結構體支持的眾多特性,展示其強大之處。 # 2. 什么是結構體? 在Go語言中 ......

    uj5u.com 2023-06-15 08:10:33 more
  • 【python基礎】函式-初識函式

    函式是帶名字的代碼塊,用于完成具體的作業,無需反復撰寫完成該作業的代碼。之前我們接觸過print函式,資料型別轉換中的int函式、str函式,還有串列中的append函式、pop函式、remove函式,以及字典中的keys函式、values函式等等,其實在正式學習函式之前,我們已經接觸了函式,只不過 ......

    uj5u.com 2023-06-15 08:10:23 more
  • rocketMQ訊息佇列簡介及其實體

    一、RocketMQ 核心的四大組件: Producer:就是訊息生產者,可以集群部署。它會先和 NameServer 集群中的隨機一臺建立長連接,得知當前要發送的 Topic 存在哪臺 Broker Master上,然后再與其建立長連接,支持多種負載平衡模式發送訊息。 Consumer:訊息消費者 ......

    uj5u.com 2023-06-15 08:10:11 more
  • jvm垃圾回收及記憶體模型

    1、了解垃圾回收之前,必須先了解記憶體模型 2、垃圾回收區域 a、 首先要標記垃圾,找出垃圾 b、Java垃圾回收(一)_java 垃圾回收_頭發慢點掉的小馬的博客-CSDN博客 垃圾回收器 方法區不需要連續的記憶體,可以選擇固定大小或者可擴展。并且還可以選擇不實作垃圾收集。相對而言,垃圾收集行為在這個 ......

    uj5u.com 2023-06-15 08:09:55 more
  • Dubbo負載均衡策略之 一致性哈希

    本文主要講解了一致性哈希演算法的原理以及其存在的資料傾斜的問題,然后引出解決資料傾斜問題的方法,最后分析一致性哈希演算法在Dubbo中的使用。通過這篇文章,可以了解到一致性哈希演算法的原理以及這種演算法存在的問題和解決方案。 ......

    uj5u.com 2023-06-15 08:09:44 more
  • Go 語言之 SQLX 高級操作 sqlx.In

    # Go 語言之 SQLX 高級操作 sqlx.In ## sqlx.In 介紹 `sqlx` is a package for Go which provides a set of extensions on top of the excellent built-in `database/sql` ......

    uj5u.com 2023-06-15 08:09:40 more
  • Scala簡介和安裝

    # 簡介 Scala是一種多范式的編程語言(多范式:多種編程方法的意思。有面向程序、面向物件、泛型、函式式四種程式設計方法),其設計的初衷是要集成面向物件編程和函式式編程的各種特性。Scala運行于Java平臺(Java虛擬機),并兼容現有的Java程式 > 官網:https://www.scala ......

    uj5u.com 2023-06-15 08:09:16 more
  • SpringBoot中Redis的基礎使用

    基礎使用 首先引入依賴 <!-- redis依賴--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </depende ......

    uj5u.com 2023-06-15 08:08:56 more
  • Java多執行緒開發系列之六:無限分解流----Fork/Join框架

    Fork譯為拆分,Join譯為合并Fork/Join框架的思路是把一個非常巨大的任務,拆分成若然的小任務,再由小任務繼續拆解。直至達到一個相對合理的任務粒度。然后執行獲得結果,然后將這些小任務的結果匯總,生成大任務的結果,直至匯總成最初巨大任務的結果。如下圖: 紅色箭頭代表拆分子任務。綠色箭頭代表返 ......

    uj5u.com 2023-06-15 08:08:44 more
  • ArcGis 欄位值統計腳本更新

    本文實作的功能主要是根據已知欄位值,給指定的名稱欄位賦上對應的值;整個處理的邏輯很簡單,就是通過判斷陳述句,判斷其他欄位值,然后給指定的欄位填上對應的值即可; 欄位統計界面如下圖所示: #腳本代碼如下 def updatefiles(ssssss): if(ssssss == 1): total="高 ......

    uj5u.com 2023-06-15 08:03:29 more