Go再進階:結構體、接口與面向對象編程

🚀 Go再進階:結構體、接口與面向對象編程

大家好!在前兩篇文章中,我們深入學習了Go語言的流程控制語句以及數組和切片的使用并且還對Go 語言的核心知識點進行了補充講解,這些知識讓我們能夠編寫出更為復雜和靈活的程序。

今天,我們將繼續探索Go語言的強大特性,深入了解結構體、接口以及Go語言獨特的面向對象編程方式。這些內容將幫助我們更好地組織和管理代碼,構建大型的、可維護的應用程序。

一、結構體:自定義的數據類型

在實際編程中,我們常常需要將不同類型的數據組合在一起,形成一個邏輯上的整體。結構體(struct)就是Go語言提供的用于滿足這種需求的工具,它允許我們創建自定義的數據類型。

1. 結構體的定義

結構體的定義使用 struct 關鍵字,基本格式如下:

type 結構體名稱 struct {字段1 數據類型字段2 數據類型// 可以有更多的字段
}

示例:定義一個表示學生的結構體

package mainimport "fmt"// 定義學生結構體
type Student struct {Name  stringAge   intGrade float32
}

2. 結構體實例化與初始化

定義好結構體后,我們可以創建結構體的實例并進行初始化。

方式一:使用鍵值對初始化

func main() {student1 := Student{Name:  "小明",Age:   18,Grade: 3.5,}fmt.Printf("學生1: 姓名 %s, 年齡 %d, 成績 %.2f\n", student1.Name, student1.Age, student1.Grade)
}

方式二:按照字段順序初始化

func main() {student2 := Student{"小紅", 17, 3.8}fmt.Printf("學生2: 姓名 %s, 年齡 %d, 成績 %.2f\n", student2.Name, student2.Age, student2.Grade)
}

3. 訪問結構體字段

通過實例變量和點號(.)操作符來訪問結構體的字段。

func main() {student := Student{Name:  "小李",Age:   19,Grade: 3.6,}// 修改字段值student.Age = 20student.Grade = 3.7fmt.Printf("學生: 姓名 %s, 年齡 %d, 成績 %.2f\n", student.Name, student.Age, student.Grade)
}

二、接口:定義行為的契約

接口(interface)是Go語言中一個非常重要的概念,它定義了一組方法的簽名,但不包含方法的實現。接口為不同類型提供了一種統一的調用方式,使得代碼更加靈活和可擴展。

1. 接口的定義

使用 interface 關鍵字定義接口,基本格式如下:

type 接口名稱 interface {方法1(參數列表) 返回值列表方法2(參數列表) 返回值列表// 可以有更多方法
}

示例:定義一個圖形接口

package mainimport "fmt"// 定義圖形接口
type Shape interface {Area() float64Perimeter() float64
}

2. 接口的實現

任何類型只要實現了接口中定義的所有方法,就被認為實現了該接口。

示例:定義矩形和圓形結構體,并實現 Shape 接口

// 矩形結構體
type Rectangle struct {Width  float64Height float64
}// 矩形的面積
func (r Rectangle) Area() float64 {return r.Width * r.Height
}// 矩形的周長
func (r Rectangle) Perimeter() float64 {return 2 * (r.Width + r.Height)
}// 圓形結構體
type Circle struct {Radius float64
}// 圓形的面積
func (c Circle) Area() float64 {return 3.14 * c.Radius * c.Radius
}// 圓形的周長
func (c Circle) Perimeter() float64 {return 2 * 3.14 * c.Radius
}

3. 接口的使用

通過接口類型的變量,可以調用實現該接口的任何類型的方法。

func main() {var s Shapes = Rectangle{Width: 5, Height: 3}fmt.Printf("矩形面積: %.2f, 周長: %.2f\n", s.Area(), s.Perimeter())s = Circle{Radius: 4}fmt.Printf("圓形面積: %.2f, 周長: %.2f\n", s.Area(), s.Perimeter())
}

4. 完整代碼示例

package main  // 聲明當前包為main,main包是可執行程序的入口包,編譯后會生成可執行文件import "fmt"  // 導入fmt包,用于格式化輸入輸出操作// 定義圖形接口Shape
// 接口在Go中是一種抽象類型,只聲明方法簽名,不實現方法
// 任何結構體只要實現了接口中所有的方法,就隱式實現了該接口
type Shape interface {Area() float64      // 聲明計算面積的方法,返回float64類型Perimeter() float64 // 聲明計算周長的方法,返回float64類型
}// 定義矩形結構體Rectangle
// 結構體是Go中的復合數據類型,用于封裝相關的數據字段
type Rectangle struct {Width  float64  // 矩形的寬度字段,類型為float64(雙精度浮點型)Height float64  // 矩形的高度字段,類型為float64
}// 為Rectangle結構體實現Area()方法(實現Shape接口的Area方法)
// (r Rectangle)是方法的接收者,表示該方法屬于Rectangle類型
// 接收者r就像其他語言中的this/self,用于訪問結構體的字段
func (r Rectangle) Area() float64 {return r.Width * r.Height  // 矩形面積公式:寬×高,返回計算結果
}// 為Rectangle結構體實現Perimeter()方法(實現Shape接口的Perimeter方法)
func (r Rectangle) Perimeter() float64 {return 2 * (r.Width + r.Height)  // 矩形周長公式:2×(寬+高),返回計算結果
}// 定義圓形結構體Circle
type Circle struct {Radius float64  // 圓形的半徑字段,類型為float64
}// 為Circle結構體實現Area()方法(實現Shape接口的Area方法)
func (c Circle) Area() float64 {return 3.14 * c.Radius * c.Radius  // 圓形面積公式:π×半徑2(這里用3.14近似π)
}// 為Circle結構體實現Perimeter()方法(實現Shape接口的Perimeter方法)
func (c Circle) Perimeter() float64 {return 2 * 3.14 * c.Radius  // 圓形周長公式:2×π×半徑(這里用3.14近似π)
}// main函數是程序的入口點,程序從這里開始執行
func main() {var s Shape  // 聲明一個Shape類型的變量s(接口類型變量)// 接口類型變量可以存儲任何實現了該接口的結構體實例(多態特性)s = Rectangle{Width: 10, Height: 5}  // 將Rectangle實例賦值給s// 此時s雖然是Shape類型,但實際存儲的是Rectangle實例,調用方法時會執行Rectangle的實現fmt.Printf("矩形的面積是:%.2f,周長是:%.2f\n", s.Area(), s.Perimeter())s = Circle{Radius: 7}  // 將Circle實例賦值給s// 同樣,s現在存儲的是Circle實例,調用方法時會執行Circle的實現fmt.Printf("圓形面積是:%.2f,周長是:%.2f\n", s.Area(), s.Perimeter())
}

執行結果

矩形的面積是:50.00,周長是:30.00
圓形面積是:153.86,周長是:43.96

三、Go語言的面向對象編程

Go語言沒有傳統面向對象語言(如Java、C++)中的“類”和“繼承”概念,但通過結構體(struct)、接口(interface)等特性,實現了封裝、組合、多態等面向對象核心思想,形成了獨特的面向對象編程范式。

1. 封裝

封裝的核心是“數據隱藏”與“行為綁定”:將數據(結構體字段)和操作數據的行為(方法)綁定在一起,并通過訪問控制限制數據的直接修改,僅允許通過預定義的方法操作數據。

在Go中,訪問控制通過標識符首字母大小寫實現:

  • 首字母大寫的字段/方法是“公開成員”,可被其他包訪問;
  • 首字母小寫的字段/方法是“私有成員”,僅允許在同一個包內訪問(注意:是“包級私有”,而非“結構體級私有”)。

示例:

package mainimport "fmt"// 定義結構體Person,包含私有字段和公開方法
type Person struct {name string // 私有字段(首字母小寫):僅main包內可訪問age  int    // 私有字段:僅main包內可訪問
}// 公開方法(首字母大寫):提供對私有字段name的讀取能力,可被其他包調用
func (p *Person) GetName() string {return p.name // 方法與結構體在同一包,可直接訪問私有字段
}// 公開方法:提供對私有字段name的修改能力
func (p *Person) SetName(newName string) {p.name = newName // 同一包內,可直接修改私有字段
}func main() {// 初始化Person實例:main函數與Person在同一包,可直接訪問私有字段進行初始化p := Person{name: "張三", age: 25}// 同一包內,甚至可以直接訪問p.name:// 注意:這里能訪問是因為main函數與Person在同一包,并非私有字段可隨意訪問fmt.Println("直接訪問私有字段name:", p.name) // 輸出:直接訪問私有字段name: 張三// 通過公開方法訪問(更規范的做法,即使在包內也推薦)fmt.Println("通過GetName()獲取:", p.GetName()) // 輸出:通過GetName()獲取: 張三p.SetName("李四")fmt.Println("修改后通過GetName()獲取:", p.GetName()) // 輸出:修改后通過GetName()獲取: 李四
}

關鍵說明:

  • 私有字段的“私有”是針對“其他包” 的限制,同一包內的所有代碼(包括函數、方法)都可以直接訪問私有字段。
  • 示例中main函數能直接訪問p.name,是因為main函數與Person結構體在同一個main包內;如果將Person放到另一個包(如model包),main包就無法直接訪問name了,必須通過GetName()等公開方法(跨包訪問的正確方式)。

2. 組合

Go通過“結構體嵌套”實現組合(而非傳統繼承),即一個結構體可以包含另一個結構體作為字段,從而復用其字段和方法,避免了繼承帶來的“類層次臃腫”和“耦合過重”問題。

示例:

package mainimport "fmt"// 地址結構體:封裝地址相關數據
type Address struct {City  string // 城市State string // 國家/地區
}// 員工結構體:通過嵌套Address結構體,復用地址相關字段
type Employee struct {Name    string  // 員工姓名Age     int     // 員工年齡Address Address // 嵌套Address結構體,組合其字段
}func main() {// 初始化員工實例,同時初始化嵌套的Addressemp := Employee{Name: "王五",Age:  30,Address: Address{City:  "北京",State: "中國",},}// 訪問組合的字段:通過“結構體.嵌套結構體.字段”的方式fmt.Printf("員工 %s 的地址是 %s, %s\n", emp.Name, emp.Address.City,  // 訪問嵌套結構體的City字段emp.Address.State) // 訪問嵌套結構體的State字段// 輸出:員工 王五 的地址是 北京, 中國
}

優勢:

  • 組合是“has-a”(有一個)的關系(如“員工有一個地址”),邏輯更清晰;
  • 可以靈活組合多個結構體,無需關心繼承層次,降低代碼耦合。

3. 多態

Go通過接口實現多態:接口定義了一組方法簽名,任何結構體只要“隱式實現”了接口的所有方法,就屬于該接口類型。在使用接口變量時,無需關心其實際存儲的結構體類型,只需調用接口方法,即可自動執行對應結構體的實現——這就是多態的核心。

示例(基于之前的Shape接口):

package mainimport "fmt"// 定義接口Shape:聲明圖形的通用行為
type Shape interface {Area() float64      // 計算面積Perimeter() float64 // 計算周長
}// 矩形結構體:實現Shape接口
type Rectangle struct {Width  float64Height float64
}// 實現Shape的Area方法
func (r Rectangle) Area() float64 {return r.Width * r.Height
}// 實現Shape的Perimeter方法
func (r Rectangle) Perimeter() float64 {return 2 * (r.Width + r.Height)
}// 圓形結構體:實現Shape接口
type Circle struct {Radius float64
}// 實現Shape的Area方法
func (c Circle) Area() float64 {return 3.14 * c.Radius * c.Radius
}// 實現Shape的Perimeter方法
func (c Circle) Perimeter() float64 {return 2 * 3.14 * c.Radius
}func main() {var s Shape // 聲明接口類型變量ss = Rectangle{Width: 10, Height: 5} // s存儲矩形實例(矩形實現了Shape)fmt.Printf("矩形:面積=%.2f, 周長=%.2f\n", s.Area(), s.Perimeter()) // 輸出:矩形:面積=50.00, 周長=30.00s = Circle{Radius: 7} // s存儲圓形實例(圓形實現了Shape)fmt.Printf("圓形:面積=%.2f, 周長=%.2f\n", s.Area(), s.Perimeter()) // 輸出:圓形:面積=153.86, 周長=43.96
}

關鍵說明:

  • 接口變量s可以存儲任何實現了Shape接口的結構體(矩形、圓形等),體現了“接口的通用性”;
  • 調用s.Area()時,Go會自動根據s中實際存儲的結構體類型(矩形/圓形),執行對應的Area實現,體現了“同一種行為,不同實現”的多態特性。

四、小結

今天我們學習了Go語言中的結構體、接口以及基于它們實現的面向對象編程方式。

  • 結構體:允許我們創建自定義的數據類型,將不同類型的數據組合在一起,方便管理和操作相關數據。
  • 接口:定義了一組方法的簽名,任何實現了這些方法的類型都被認為實現了該接口,為不同類型提供統一調用方式,增強代碼的靈活性和擴展性。
  • 面向對象編程:Go的面向對象編程更注重“組合優于繼承”“接口隱式實現”,通過結構體封裝數據與行為,通過組合復用代碼,通過接口實現多態,整體設計簡潔靈活,避免了傳統面向對象的復雜特性。

五、實戰:智能設備管理系統

以下實戰案例是一個更貼近實際開發場景的實戰案例:智能設備管理系統

以下案例會綜合運用結構體接口封裝組合多態等知識點,模擬一個管理多種智能設備(如智能燈、恒溫器、攝像頭)的系統,功能包括設備狀態監控、遠程控制、數據統計等,更具實用性和擴展性。

實戰案例:智能設備管理系統

需求說明

實現一個能管理多種智能設備的系統,支持:

  1. 設備的啟動/關閉/狀態查詢(通用功能);
  2. 每種設備的特有功能(如燈調節亮度、恒溫器調節溫度);
  3. 統一管理所有設備,批量執行操作并統計狀態。
完整代碼實現
package mainimport ("fmt""time"
)// -------------- 1. 定義核心接口(多態基礎)--------------
// Device 接口:所有智能設備的通用行為契約
type Device interface {ID() string               // 獲取設備唯一標識Start() error             // 啟動設備Shutdown() error          // 關閉設備GetStatus() string        // 獲取設備當前狀態DeviceType() string       // 獲取設備類型
}// -------------- 2. 基礎結構體(封裝與組合)--------------
// BaseDevice 基礎設備結構體:封裝所有設備的共性字段和通用方法
// 私有字段通過公開方法訪問(封裝),供其他設備組合復用(組合)
type BaseDevice struct {deviceID   string    // 設備唯一ID(私有字段,包內可見)name       string    // 設備名稱(私有字段)status     string    // 設備狀態(私有字段:"off" / "on")createdAt  time.Time // 設備創建時間(私有字段)
}// 初始化基礎設備(構造函數)
func NewBaseDevice(deviceID, name string) BaseDevice {return BaseDevice{deviceID:  deviceID,name:      name,status:    "off", // 初始狀態為關閉createdAt: time.Now(),}
}// ID 實現Device接口的ID方法(公開方法,供外部獲取設備ID)
func (b *BaseDevice) ID() string {return b.deviceID
}// Start 基礎啟動邏輯(通用實現,可被組合的設備復用)
func (b *BaseDevice) Start() error {if b.status == "on" {return fmt.Errorf("設備已啟動")}b.status = "on"return nil
}// Shutdown 基礎關閉邏輯(通用實現)
func (b *BaseDevice) Shutdown() error {if b.status == "off" {return fmt.Errorf("設備已關閉")}b.status = "off"return nil
}// GetStatus 實現Device接口的狀態查詢(通用實現)
func (b *BaseDevice) GetStatus() string {return fmt.Sprintf("%s(%s)", b.name, b.status)
}// -------------- 3. 具體設備實現(組合與多態)--------------// 智能燈(繼承基礎設備的功能,添加特有功能)
type SmartLight struct {BaseDevice       // 組合基礎設備(復用ID/Start/Shutdown等功能)Brightness int   // 亮度(0-100,特有字段)Color      string // 燈光顏色(特有字段)
}// NewSmartLight 智能燈構造函數
func NewSmartLight(deviceID, name string) *SmartLight {return &SmartLight{BaseDevice: NewBaseDevice(deviceID, name),Brightness: 50, // 默認亮度50%Color:      "white",}
}// DeviceType 實現Device接口,返回設備類型(特有實現)
func (s *SmartLight) DeviceType() string {return "智能燈"
}// AdjustBrightness 智能燈特有方法:調節亮度
func (s *SmartLight) AdjustBrightness(level int) error {if s.BaseDevice.status != "on" {return fmt.Errorf("設備未啟動,無法調節亮度")}if level < 0 || level > 100 {return fmt.Errorf("亮度值必須在0-100之間")}s.Brightness = levelreturn nil
}// 恒溫器(另一種設備,同樣組合基礎設備)
type Thermostat struct {BaseDevice     // 組合基礎設備TargetTemp float64 // 目標溫度(特有字段)CurrentTemp float64 // 當前溫度(特有字段)
}// NewThermostat 恒溫器構造函數
func NewThermostat(deviceID, name string) *Thermostat {return &Thermostat{BaseDevice: NewBaseDevice(deviceID, name),TargetTemp: 25.0, // 默認目標溫度25℃CurrentTemp: 23.5,}
}// DeviceType 實現Device接口,返回設備類型
func (t *Thermostat) DeviceType() string {return "恒溫器"
}// SetTargetTemp 恒溫器特有方法:設置目標溫度
func (t *Thermostat) SetTargetTemp(temp float64) error {if t.BaseDevice.status != "on" {return fmt.Errorf("設備未啟動,無法設置溫度")}if temp < 16 || temp > 30 {return fmt.Errorf("溫度范圍必須在16-30℃之間")}t.TargetTemp = tempreturn nil
}// 攝像頭(第三種設備)
type Camera struct {BaseDevice   // 組合基礎設備Resolution string // 分辨率(特有字段)IsRecording bool  // 是否正在錄像(特有字段)
}// NewCamera 攝像頭構造函數
func NewCamera(deviceID, name string) *Camera {return &Camera{BaseDevice: NewBaseDevice(deviceID, name),Resolution: "1080p",IsRecording: false,}
}// DeviceType 實現Device接口,返回設備類型
func (c *Camera) DeviceType() string {return "攝像頭"
}// StartRecording 攝像頭特有方法:開始錄像
func (c *Camera) StartRecording() error {if c.BaseDevice.status != "on" {return fmt.Errorf("設備未啟動,無法錄像")}if c.IsRecording {return fmt.Errorf("已在錄像中")}c.IsRecording = truereturn nil
}// -------------- 4. 設備管理器(統一管理與多態應用)--------------
// DeviceManager 設備管理器:統一管理所有設備
type DeviceManager struct {devices map[string]Device // 用接口類型存儲所有設備(多態關鍵)
}// NewDeviceManager 初始化設備管理器
func NewDeviceManager() *DeviceManager {return &DeviceManager{devices: make(map[string]Device),}
}// AddDevice 添加設備到管理器
func (m *DeviceManager) AddDevice(d Device) {m.devices[d.ID()] = d
}// StartAll 批量啟動所有設備
func (m *DeviceManager) StartAll() {fmt.Println("\n===== 批量啟動所有設備 =====")for id, d := range m.devices {err := d.Start()if err != nil {fmt.Printf("設備[%s]啟動失敗:%v\n", id, err)} else {fmt.Printf("設備[%s]啟動成功:%s\n", id, d.GetStatus())}}
}// ShutdownAll 批量關閉所有設備
func (m *DeviceManager) ShutdownAll() {fmt.Println("\n===== 批量關閉所有設備 =====")for id, d := range m.devices {err := d.Shutdown()if err != nil {fmt.Printf("設備[%s]關閉失敗:%v\n", id, err)} else {fmt.Printf("設備[%s]關閉成功:%s\n", id, d.GetStatus())}}
}// ShowStatus 展示所有設備狀態
func (m *DeviceManager) ShowStatus() {fmt.Println("\n===== 所有設備狀態 =====")for _, d := range m.devices {fmt.Printf("[%s] %s:%s\n", d.ID(), d.DeviceType(), d.GetStatus())}
}// -------------- 5. 主函數(演示流程)--------------
func main() {// 1. 創建設備管理器manager := NewDeviceManager()// 2. 創建各種設備(結構體實例化)light := NewSmartLight("light_001", "客廳燈")thermostat := NewThermostat("thermo_001", "臥室恒溫器")camera := NewCamera("cam_001", "門口攝像頭")// 3. 將設備添加到管理器(接口類型存儲,多態)manager.AddDevice(light)manager.AddDevice(thermostat)manager.AddDevice(camera)// 4. 展示初始狀態(所有設備默認關閉)manager.ShowStatus()// 5. 批量啟動所有設備manager.StartAll()// 6. 調用各設備的特有功能(體現封裝的字段訪問控制)fmt.Println("\n===== 設備特有功能操作 =====")// 智能燈調節亮度if err := light.AdjustBrightness(80); err != nil {fmt.Println("調節亮度失敗:", err)} else {fmt.Printf("客廳燈亮度已調節至%d%%\n", light.Brightness)}// 恒溫器設置目標溫度if err := thermostat.SetTargetTemp(26.5); err != nil {fmt.Println("設置溫度失敗:", err)} else {fmt.Printf("臥室恒溫器目標溫度已設置為%.1f℃\n", thermostat.TargetTemp)}// 攝像頭開始錄像if err := camera.StartRecording(); err != nil {fmt.Println("錄像啟動失敗:", err)} else {fmt.Println("門口攝像頭已開始錄像")}// 7. 批量關閉所有設備manager.ShutdownAll()
}
代碼執行結果
===== 所有設備狀態 =====
[light_001] 智能燈:客廳燈(off)
[thermo_001] 恒溫器:臥室恒溫器(off)
[cam_001] 攝像頭:門口攝像頭(off)===== 批量啟動所有設備 =====
設備[light_001]啟動成功:客廳燈(on)
設備[thermo_001]啟動成功:臥室恒溫器(on)
設備[cam_001]啟動成功:門口攝像頭(on)===== 設備特有功能操作 =====
客廳燈亮度已調節至80%
臥室恒溫器目標溫度已設置為26.5℃
門口攝像頭已開始錄像===== 批量關閉所有設備 =====
設備[light_001]關閉成功:客廳燈(off)
設備[thermo_001]關閉成功:臥室恒溫器(off)
設備[cam_001]關閉成功:門口攝像頭(off)

案例知識點解析

這個案例完整覆蓋了結構體、接口、面向對象的核心知識點,具體對應如下:

  1. 結構體(自定義數據類型)

    • 定義了BaseDevice(基礎設備)、SmartLight(智能燈)等結構體,封裝了設備的屬性(如deviceIDstatusBrightness),實現了數據的結構化管理。
    • 通過構造函數(如NewSmartLight)規范結構體實例化過程。
  2. 接口(行為契約與多態)

    • Device接口定義了所有設備的通用行為(Start()/Shutdown()等),任何設備只要實現了這些方法,就屬于Device類型。
    • 設備管理器DeviceManager通過map[string]Device存儲設備,利用接口的多態特性,統一管理不同類型的設備(無需關心具體是燈還是攝像頭)。
  3. 封裝(數據隱藏與訪問控制)

    • BaseDevice中的字段(如deviceIDstatus)首字母小寫,為包內私有,外部無法直接修改,只能通過公開方法(如Start()ID())操作,保證數據安全性。
    • 例如:設備狀態status只能通過Start()/Shutdown()方法修改,避免了直接賦值導致的狀態混亂。
  4. 組合(代碼復用)

    • 所有具體設備(SmartLight/Thermostat/Camera)都嵌套了BaseDevice,復用了基礎功能(如設備ID管理、啟動/關閉邏輯),避免重復代碼。
    • 組合是“has-a”關系(如“智能燈有一個基礎設備的屬性”),比傳統繼承更靈活,設備可自由組合多個基礎功能(如未來可添加“網絡模塊”結構體實現聯網功能)。
  5. 多態(同一接口,不同實現)

    • 設備管理器調用d.Start()時,會根據d實際存儲的設備類型(燈/恒溫器/攝像頭)執行對應實現(雖然BaseDevice提供了默認Start(),但未來可在具體設備中重寫以實現特殊邏輯)。
    • 新增設備(如智能窗簾)時,只需實現Device接口,無需修改管理器代碼,符合“開閉原則”,擴展性極強。

這個案例更貼近實際開發中的“設備管理”“插件系統”等場景,通過接口抽象通用行為,通過組合復用代碼,通過封裝保證數據安全,充分體現了Go語言面向對象編程的簡潔與靈活。

通過這個實戰案例,希望能幫助大家更好地理解和運用今天所學的知識。不斷實踐,你將在Go語言的學習中取得更大的進步!
在這里插入圖片描述

專欄預告:下一篇深入Go語言學習并發編程與錯誤處理,我們將探索Go語言強大的并發編程能力以及優雅的錯誤處理機制,這將使你能夠開發出高性能、健壯的Go應用程序,敬請期待! 😊

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/91329.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/91329.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/91329.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python入門第六課:現代開發與前沿技術

異步編程(asyncio) 1. 協程基礎 import asyncio import time# 定義協程函數 async def say_after(delay, message):await asyncio.sleep(delay)print(message)# 主協程 async def main():print(f"開始時間: {time.strftime(%X)}")# 順序執行await say_after(2, 你…

STM32移植LVGL9.2.1教程

一、環境說明 &#xff08;1&#xff09;開發板&#xff1a;STM32F401RCT6核心板&#xff08;網上很多&#xff0c;價格只有幾塊錢&#xff09; &#xff08;2&#xff09;屏幕&#xff1a;2.8寸spi屏gt911觸摸 轉接板&#xff08;某寶有賣&#xff0c;沒有推廣自行搜索&…

python學智能算法(二十九)|SVM-拉格朗日函數求解中-KKT條件理解

【1】引言 前序學習階段中&#xff0c;我們掌握了最佳分割超平面對應的構造拉格朗日函數極值為&#xff1a; L(w,b,α)∑i1mαi?12∑i,j1mαiαjyiyjxiTxjL(w,b,\alpha)\sum_{i1}^{m}\alpha_{i}-\frac{1}{2}\sum_{i,j1}^{m}\alpha_{i}\alpha_{j}y_{i}y_{j}x_{i}^{T}x_{j}L(w,…

大模型應用開發1-認識大模型

1.基礎概念 1.1 AI的概念&#xff1a; AI&#xff0c;??智能&#xff08;Artificial Intelligence&#xff09;&#xff0c;使機器能夠像?類?樣思考、學習和解決問題的技術。AI發展?今?概可以分為三個階段&#xff1a;其中&#xff0c;深度學習領域的自然語言處理&#…

Linux 遠程連接解析:SSH 協議理論與應用

Linux 遠程連接解析&#xff1a;SSH 協議理論與應用在網絡互聯的時代&#xff0c;遠程管理服務器已成為常態。SSH&#xff08;Secure Shell&#xff09;作為一種安全的網絡協議&#xff0c;憑借其加密機制和靈活的功能&#xff0c;成為 Linux 系統遠程操作的事實標準。本文將從…

ubuntu22.04系統入門 linux入門 簡單命令基礎復習 實現以及實踐

以下有免費的4090云主機提供ubuntu22.04系統的其他入門實踐操作 地址&#xff1a;星宇科技 | GPU服務器 高性能云主機 云服務器-登錄 相關兌換碼星宇社區---4090算力卡免費體驗、共享開發社區-CSDN博客 兌換碼要是過期了&#xff0c;可以私信我獲取最新兌換碼&#xff01;&a…

軟考中級-信息安全工程師-每日一學(1)

前提概要本文章主要用于分享軟考中級-信息安全工程師-學習&#xff0c;以下是一些個人理解&#xff0c;請大家結合參考其他文章中的相關信息及個人經驗進行歸納和補充&#xff0c;內容會存在一定錯誤&#xff0c;希望讀者多多評論批評&#xff0c;本人在此先說感謝啦。1.密碼學…

EEG手工特征提取總結

目錄一、引言EEG信號簡介EEG特征提取的重要性本次匯報目的與內容概述二、EEG信號核心特征時域特征 (Time-Domain Features)頻域特征 (Frequency-Domain Features)三、EEG信號高級特征時頻域特征 (Time-Frequency Domain Features)空間域特征 (Spatial-Domain Features)復雜動力…

React 路由守衛

下面&#xff0c;我們來系統的梳理關于 React Router 路由守衛 的基本知識點&#xff1a;一、路由守衛概述 1.1 什么是路由守衛 路由守衛是一種在用戶導航到特定路由之前或離開特定路由時執行邏輯的機制。它允許開發者控制用戶訪問權限、驗證條件或執行數據預加載等操作。 1.2 …

7月31日作業

1&#xff1a;請使用函數模板&#xff0c;寫一個能夠針對所有數據類型的數據的快速排序函數 并多寫幾個數組做測試代碼#include <iostream> #include <cstring> #include <cstdlib> #include <unistd.h> #include <sstream> #include <vector…

客戶服務自動化:如何用CRM減少50%人工工單?

通過CRM系統實現客戶服務自動化&#xff0c;企業可以顯著減少人工工單的數量&#xff0c;提升整體服務效率。那么如何利用CRM系統實現客戶服務自動化&#xff1f;幫助企業從根本上解決人工工單處理的難題&#xff0c;提升服務質量&#xff0c;優化資源配置&#xff0c;最終實現…

常用設計模式系列(十四)—模板方法模式

常用設計模式系列&#xff08;十四&#xff09;—模板方法模式 第一節 前言 之前我完成了創建型設計模式和結構型設計模式&#xff0c;我們今天將踏入設計模式的第三章&#xff1a;行為型設計模式&#xff0c;你是否還記得什么是行為型設計模式嗎&#xff1f;行為型模式&#x…

DoRA詳解:從LoRA到權重分解的進化

DoRA??是一種用于??大語言模型&#xff08;LLM&#xff09;微調??的技術&#xff0c;全稱為 ??"Weight-Decomposed Low-Rank Adaptation"??&#xff08;權重分解的低秩自適應&#xff09;。它是對現有微調方法&#xff08;如 ??LoRA??&#xff09;的改…

RocksDB關鍵設計詳解

0 說明 近日工作中使用了 RocksDB。RocksDB 的優點此處無需多說&#xff0c;它的一個 feature 是其有很多優化選項用于對 RocksDB 進行調優。欲熟悉這些參數&#xff0c;必須對其背后的原理有所了解&#xff0c;本文主要整理一些 RocksDB 的 wiki 文檔&#xff0c;以備自己參考…

Kotlin -> 普通Lambda vs 掛起Lambda

1. 普通Lambda vs 掛起Lambda的本質區別 1.1 普通Lambda&#xff08;同步執行&#xff09; val lambda: (Int) -> String { it.toString() }// 編譯器生成&#xff1a; class Lambda$1 : Function1<Int, String> {override fun invoke(p1: Int): String {return p1.t…

Apache Ignite 中如何配置和啟用各類監控指標

這段文檔是關于 Apache Ignite 中如何配置和啟用各類監控指標&#xff08;Metrics&#xff09; 的詳細說明。核心思想是&#xff1a;“指標收集有性能開銷&#xff0c;因此默認不開啟所有指標&#xff0c;需要你按需手動開啟。” 下面我們來逐層拆解、通俗易懂地理解這些內容。…

uniapp x swiper/image組件mode=“aspectFit“ 圖片有的閃現后黑屏

部分安卓機針對大寫.JPG 有的豎圖正常&#xff0c;橫圖/正方形不對。解決方案&#xff1a;加border-radius: 1rpx;就行<!-- 圖片預覽彈出框 --><fui-backdrop v-model:visible"imgPreviewVisible" :closable"true" onclick"imgPreviewVisibl…

conda安裝jupter

conda自帶的jupter本來在base里沒有在pytorch環境中 安裝jupter conda install nb_conda 此擴展程序在 Jupyter 文件瀏覽器中添加了一個 Conda 選項卡。選擇 Conda 選項卡將顯示&#xff1a; 當前存在的 Conda 環境列表當前配置的通道中可用的 Conda 包列表&#xff08;htt…

嵌入式操作系統快速入門(1):快速入門操作系統常見基礎概念

快速體會操作系統常見基礎概念 1 初識基本概念 1.1 操作系統 一個軟件程序&#xff1b;用于解決計算機多任務執行時的資源爭搶問題&#xff1b;管理計算機中的各種資源&#xff0c;確保計算機正常完成各種工作&#xff08;任務&#xff09;&#xff0c;解決多任務環境中任務的調…

網絡安全-同形異義字攻擊:眼見并非為實(附案例詳解)

什么是同形異義字攻擊&#xff1f;對人眼而言&#xff0c;一切看起來完全正常。但實際上&#xff0c;例如單詞 Ηоmоgraph 并不完全等同于單詞 Homograph。它們之間的差異非常細微&#xff0c;難以察覺。Ηоmоgraph 實際上包含了幾個非拉丁字母。在本例中&#xff0c;我們將…