【Go】P3 Go語言程序結構

Go語言程序結構

  • Go語言程序結構
    • 命名規則與編程慣例
    • 核心規則
    • 四種聲明語句詳解
      • var聲明:變量聲明
      • const聲明:常量聲明
      • type聲明:類型定義
      • func聲明:函數聲明
    • 簡短變量聲明(:=)
      • 使用規則和限制
    • 指針:安全的內存地址操作
      • 基本概念和操作
      • 結構體指針的自動解引用
    • new函數與內存分配
      • new vs make的區別
    • 變量生命周期與內存管理
      • 生命周期規則
    • 賦值操作與元組賦值
    • 包管理與文件組織
      • 包聲明與導入
      • 包的初始化與init函數
      • 執行順序
    • 作用域規則詳解
      • 作用域層級
      • 變量遮蔽示例

Go語言程序結構

命名規則與編程慣例

Go語言通過簡潔的命名規則實現了代碼的清晰性和可維護性。


核心規則

導出機制:首字母大小寫決定標識符的可見性

  • 首字母大寫:導出的(公開),包外可訪問
  • 首字母小寫:未導出的(私有),僅包內可訪問
  • 例如:fmt 包的 Printf 函數就是導出的,可以在fmt包外部訪問

命名風格:采用駝峰命名法,避免下劃線

package main// 導出的變量和函數(首字母大寫)
var PublicVar int = 100
func PublicFunction() {fmt.Println("可以被其他包調用")
}// 未導出的變量和函數(首字母小寫)
var privateVar string = "private"
func privateFunction() {fmt.Println("僅本包內可用")
}// 良好的命名示例
var userName string        // 駝峰命名
var HTTPClient *http.Client // 縮寫詞保持大寫
const MaxConnections = 100  // 常量

實踐要點

  • 包名使用小寫單詞,簡潔明了
  • 常量名要有意義,不基于數值命名
  • 縮寫詞保持一致的大小寫(URL、HTTP、JSON)

四種聲明語句詳解

Go語言提供四種聲明語句,每種都有特定的用途和語法規則。

var聲明:變量聲明

// 基本語法
var age int                 // 聲明,使用零值
var name string = "Go"      // 聲明并初始化
var score = 95.5            // 類型推斷// 批量聲明
var (width  int = 100height int = 200title  string = "Go編程"
)// 多變量聲明
var x, y int = 10, 20

零值機制:未初始化變量自動設置為類型對應的零值

  • 數值類型:0
  • 布爾類型:false
  • 字符串:“”
  • 指針、切片、映射:nil

const聲明:常量聲明

// 基本常量
const Pi = 3.14159
const AppName string = "MyApp"// 常量組
const (StatusOK     = 200StatusError  = 500StatusNotFound = 404
)// 無類型常量的威力
const (Big   = 1 << 100  // 1 << 100 表示將數字 1 向左位移 100 位,相當于計算 2^100Small = Big >> 99 // Big >> 99 表示將 Big 向右位移 99 位,右移 99 位后得到 2^100 / 2^99 = 2^1 = 2
)

type聲明:類型定義

// 定義新類型(具有新的方法集)
type Celsius float64
type UserID int// 為新類型添加方法
func (c Celsius) String() string {return fmt.Sprintf("%.1f°C", c)
}// 類型別名(Go 1.9+)
type StringSlice = []string  // 完全等價于[]string// 復雜類型定義
type Person struct {Name stringAge  int
}type Handler func(http.ResponseWriter, *http.Request)

func聲明:函數聲明

// 基本函數
func add(a, b int) int {return a + b
}// 多返回值
func divmod(dividend, divisor int) (quotient, remainder int) {quotient = dividend / divisorremainder = dividend % divisorreturn  // 命名返回值可省略return后的變量名
}// 錯誤處理模式
func divide(a, b float64) (float64, error) {if b == 0 {return 0, errors.New("除數不能為零")}return a / b, nil
}// 變參函數
func sum(numbers ...int) int {		//numbers 是一個可變參數,意味著這個函數可以接受任意數量的 int 類型參數total := 0for _, num := range numbers {total += num}return total
}

簡短變量聲明(:=)

:=是Go語言的語法糖,讓變量聲明更加簡潔。

使用規則和限制

func example() {// 基本使用name := "Go語言"           // 等價于 var name = "Go語言"count := 42               // 類型推斷為int// 多變量聲明x, y := 10, 20// 處理函數返回值result, err := strconv.Atoi("123")		// strconv.Atoi() 是Go標準庫中的函數,用于將字符串轉換為整數(ASCII to Integer的縮寫)if err != nil {log.Fatal(err)}// 重新聲明(至少一個新變量)result, status := calculate(), true  // result被重新聲明
}

關鍵限制

  • 只能在函數內部使用
  • 至少要聲明一個新變量
  • 會產生變量遮蔽問題

指針:安全的內存地址操作

Go語言的指針比C語言更安全,不支持指針運算。

基本概念和操作

func pointerExample() {// 基本指針操作x := 42p := &x        // p是指向x的指針fmt.Println("x的值:", x)   // 42fmt.Println("x的地址:", p) // 0x... 內存地址fmt.Println("指針指向的值:", *p) // 42// 通過指針修改值*p = 100fmt.Println("修改后x的值:", x)  // 100// 指針的零值var ptr *intfmt.Println("指針零值:", ptr)        // <nil>fmt.Println("是否為nil:", ptr == nil) // true
}// 指針作為函數參數實現引用傳遞
func swap(x, y *int) {*x, *y = *y, *x
}func main() {a, b := 10, 20fmt.Printf("交換前: a=%d, b=%d\n", a, b)swap(&a, &b)fmt.Printf("交換后: a=%d, b=%d\n", a, b)
}

結構體指針的自動解引用

type Person struct {Name stringAge  int
}func structPointerExample() {p := &Person{"Alice", 30}// 以下兩種寫法等價(自動解引用)p.Age = 31              // 簡潔寫法(*p).Name = "Bob"       // 顯式解引用
}
  • Person{"Alice", 30}:創建一個Person實例,Name為"Alice",Age為30。
  • &:取地址操作符,獲取該實例的內存地址
  • p:是一個指向Person的指針變量

new函數與內存分配

new函數用于分配內存并返回指向零值的指針。

new vs make的區別

// new: 分配零值內存,返回指針
func newExample() {p := new(int)        // 分配一塊內存來存儲 int 類型的值fmt.Println(*p)      // 0 (int的零值)*p = 42// 等價寫法var x intp2 := &x
}// make: 用于slice、map、channel的初始化
func makeExample() {// slices := make([]int, 5)      // 長度為5的slices2 := make([]int, 5, 10) // 長度5,容量10// mapm := make(map[string]int)m["key"] = 42// channelc := make(chan int)      // 無緩沖channelc2 := make(chan int, 5)  // 緩沖區大小為5
}
  • p := new(int) 等價于 var x int; p2 := &x

  • make slice 中長度與容量的定義:

    s := make([]int, 3, 8)
    // 底層數組: [0, 0, 0, _, _, _, _, _]
    //           |<-長度3->|<--容量8-->|
    //           可訪問部分    總共可用空間
    
  • 緩沖區是channel內部用來臨時存儲數據的空間

    ch := make(chan int, 3)  // 可以存儲3個值的緩沖區
    ch <- 1  // 不阻塞
    ch <- 2  // 不阻塞
    ch <- 3  // 不阻塞
    ch <- 4  // 這里會阻塞,因為緩沖區已滿
    

    無緩沖channel:適合需要嚴格同步的場景,如等待goroutine完成
    帶緩沖channel:適合生產者-消費者模式,可以提高程序性能和解耦
    緩沖區本質上就是一個先進先出(FIFO)的隊列,用來在發送方和接收方之間臨時存儲數據。


變量生命周期與內存管理

Go的垃圾回收器自動管理內存,但理解變量生命周期有助于寫出更高效的代碼。

生命周期規則

var globalVar = "全局變量"  // 程序整個生命周期func lifeCycleExample() {localVar := "局部變量"   // 函數執行期間// 變量逃逸:局部變量返回后仍被引用p := &localVarreturn p  // localVar逃逸到堆上
}func memoryExample() {// 棧分配:函數內局部變量x := 42// 堆分配:new創建或變量逃逸p := new(int)// slice在堆上分配底層數組s := make([]int, 1000)// 當這些變量不再被引用時,GC會回收內存
}

賦值操作與元組賦值

Go支持簡潔的多重賦值語法。

func assignmentExample() {// 基本賦值x := 10x = 20// 元組賦值:變量交換a, b := 1, 2a, b = b, a  // 一行完成交換// 函數多返回值賦值quotient, remainder := divmod(17, 5)	//divmod 除法// 使用空白標識符忽略不需要的值// strconv.Atoi() 函數將字符串轉換為整數,返回兩個值:轉換后的整數和可能的錯誤_, err := strconv.Atoi("123")  // 忽略轉換結果value, _ := strconv.Atoi("456") // 忽略錯誤// 結構體字段賦值type Point struct { X, Y int }var p Pointp.X, p.Y = 10, 20
}

包管理與文件組織

Go程序由包組成,包是代碼組織和復用的基本單元。

包聲明與導入

// main.go - 主程序包
package mainimport ("fmt"                    // 標準庫"net/http"              // 標準庫子包"github.com/gin-gonic/gin"  // 第三方包// 導入別名f "fmt"h "net/http"// 匿名導入(僅執行init函數)_ "github.com/lib/pq"
)func main() {f.Println("使用別名導入")
}
// utils/helper.go - 工具包
package utilsimport "strings"// 導出函數(首字母大寫)
func FormatName(name string) string {return strings.Title(strings.ToLower(name))
}// 未導出函數(首字母小寫)
func internalHelper() {// 僅包內使用
}

包的初始化與init函數

package mainimport "fmt"// 包級變量初始化(按依賴順序)
var config = loadConfig()// init函數:在main前執行
func init() {fmt.Println("第一個init")setupLogging()
}func init() {fmt.Println("第二個init")connectDatabase()
}func main() {fmt.Println("main函數執行")
}
  • Go允許在同一個包中定義多個init函數
  • 這些函數會在main函數之前自動執行
  • 執行順序按照它們在源文件中出現的順序

執行順序

當程序運行時,執行順序如下:

  1. 包級變量初始化:loadConfig()被調用,config變量被初始化
  2. 第一個init函數:輸出"第一個init",執行setupLogging()
  3. 第二個init函數:輸出"第二個init",執行connectDatabase()
  4. main函數:最后執行,輸出"main函數執行"

作用域規則詳解

Go語言有清晰的作用域層次結構。

作用域層級

package main  // 包作用域開始import "fmt"  // fmt在文件作用域var globalVar = "包級變量"  // 包作用域func scopeExample() {  // 函數作用域開始var functionVar = "函數變量"if true {  // 塊作用域開始var blockVar = "塊變量"fmt.Println(globalVar, functionVar, blockVar)// 變量遮蔽globalVar := "局部變量遮蔽全局變量"fmt.Println(globalVar)  // 打印局部變量}  // 塊作用域結束// fmt.Println(blockVar)  // 錯誤:blockVar超出作用域fmt.Println(globalVar)  // 訪問包級變量
}func anotherFunction() {fmt.Println(globalVar)  // 可以訪問包級變量// fmt.Println(functionVar)  // 錯誤:無法訪問其他函數的變量
}

變量遮蔽示例

var message = "全局消息"func shadowExample() {fmt.Println(message)  // "全局消息"message := "函數消息"  // 遮蔽全局變量fmt.Println(message)  // "函數消息"{message := "塊消息"  // 遮蔽函數變量fmt.Println(message)  // "塊消息"}fmt.Println(message)  // "函數消息"
}

下一篇博文,將以結構化分享 go 語言數據結構。

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

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

相關文章

【機器學習深度學習】知識蒸餾實戰:讓小模型擁有大模型的智慧

目錄 引言&#xff1a;模型壓縮的迫切需求 一、知識蒸餾的核心原理 1.1 教師-學生模式 1.2 軟目標&#xff1a;知識傳遞的關鍵 1.3 蒸餾損失函數 二、實戰&#xff1a;Qwen模型蒸餾實現 2.1 環境配置與模型加載 2.2 蒸餾損失函數實現 2.3 蒸餾訓練流程 2.4 訓練優化技…

基于MCP提示構建工作流程自動化的實踐指南

引言 在現代工作和生活中&#xff0c;我們經常被各種重復性任務所困擾——從每周的膳食計劃到代碼審查反饋&#xff0c;從文檔更新到報告生成。這些任務雖然不復雜&#xff0c;卻消耗了大量寶貴時間。MCP&#xff08;Model Context Protocol&#xff09;提示技術為解決這一問題…

apache-tomcat-11.0.9安裝及環境變量配置

一、安裝從官網上下載apache-tomcat-11.0.9,可以下載exe可執行文件版本&#xff0c;也可以下載zip版本&#xff0c;本文中下載的是zip版本。將下載的文件解壓到指定目錄&#xff1b;打開tomcat安裝目錄下“\conf\tomcat-users.xml”文件&#xff1b;輸入以下代碼&#xff0c;pa…

Java 大視界 -- Java 大數據機器學習模型在電商用戶生命周期價值評估與客戶關系精細化管理中的應用(383)

Java 大視界 -- Java 大數據機器學習模型在電商用戶生命周期價值評估與客戶關系精細化管理中的應用&#xff08;383&#xff09;引言&#xff1a;正文&#xff1a;一、電商用戶運營的 “糊涂賬”&#xff1a;不是所有客戶都該被討好1.1 運營者的 “三大錯覺”1.1.1 錯把 “過客…

豆包新模型與PromptPilot工具深度測評:AI應用開發的全流程突破

目錄引言一、豆包新模型技術解析1.1 豆包新模型介紹1.2 核心能力突破1.2.1 情感交互能力1.2.2 推理與編碼能力二、PromptPilot工具深度測評2.1 PromptPilot介紹2.2 工具架構與核心功能2.3 一個案例講通&#xff1a;市場調研報告2.3.1 生成Prompt2.3.2 批量集生成2.3.3 模擬數據…

【代碼隨想錄day 12】 力扣 144.145.94.前序遍歷中序遍歷后序遍歷

視頻講解&#xff1a;https://www.bilibili.com/video/BV1Wh411S7xt/?vd_sourcea935eaede74a204ec74fd041b917810c 文檔講解&#xff1a;https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E9%80%92%E5%BD%92%E9%81%8D%E5%8E%86.html#%E5%85%B6%E4%BB%96%E8%A…

【Unity】 HTFramework框架(六十七)UDateTime可序列化日期時間(附日期拾取器)

更新日期&#xff1a;2025年8月6日。 Github 倉庫&#xff1a;https://github.com/SaiTingHu/HTFramework Gitee 倉庫&#xff1a;https://gitee.com/SaiTingHu/HTFramework 索引一、UDateTime可序列化日期時間1.定義UDateTime字段2.日期拾取器&#xff08;編輯器&#xff09;3…

Docker的安裝,服務器與客戶端之間的通信

目錄 1、Docker安裝 1.1主機配置 1.2apt源的修改 1.3apt安裝 2、客戶端與服務端通信 2.1服務端配置 2.1.1創建鏡像存放目錄 2.1.2修改配置文件 2.2端口通信 2.3SSH連接 2.3.1生成密鑰 2.3.2傳輸密鑰 2.3.3測試連接 1、Docker安裝 1.1主機配置 我使用的兩臺主機是…

【算法專題訓練】09、累加子數組之和

1、題目&#xff1a;LCR 010. 和為 K 的子數組 https://leetcode.cn/problems/QTMn0o/description/ 給定一個整數數組和一個整數 k &#xff0c;請找到該數組中和為 k 的連續子數組的個數。示例 1&#xff1a; 輸入:nums [1,1,1], k 2 輸出: 2 解釋: 此題 [1,1] 與 [1,1] 為兩…

WinXP配置一鍵還原的方法

使用系統自帶的系統還原功能&#xff1a;啟用系統還原&#xff1a;右鍵點擊 “我的電腦”&#xff0c;選擇 “屬性”&#xff0c;切換到 “系統還原” 選項卡&#xff0c;確保 “在所有驅動器上關閉系統還原” 未被勾選&#xff0c;并為系統驅動器&#xff08;C:&#xff09;設…

基于模式識別的訂單簿大單自動化處理系統

一、系統概述 在金融交易領域&#xff0c;訂單簿承載著海量的交易信息&#xff0c;其中大單的處理對于市場流動性和價格穩定性有著關鍵影響。基于模式識別的訂單簿大單自動化處理系統旨在通過智能算法&#xff0c;精準識別訂單簿中的大單特征&#xff0c;并實現自動化的高效處理…

table行內--圖片預覽--image

需求&#xff1a;點擊預覽&#xff0c;進行預覽。支持多張圖切換思路&#xff1a;使用插槽&#xff1b;src : 展示第一張圖&#xff1b;添加preview-src-list ,用于點擊預覽。使用插槽&#xff08;UI組件--> avue&#xff09;column: 測試數據

560. 和為 K 的子數組 - 前綴和思想

560. 和為 K 的子數組 - 前綴和思想 在算法題中&#xff0c;前綴和是一種能快速計算 “數組中某段連續元素之和” 的預處理方法&#xff0c;核心思路是 “提前計算并存儲中間結果&#xff0c;避免重復計算” 前綴和的定義&#xff1a; 對于一個數組 nums&#xff0c;我們可以創…

Python金融分析:從基礎到量化交易的完整指南

Python金融分析:從基礎到量化交易的完整指南 引言:Python在金融領域的核心地位 在量化投資規模突破5萬億美元的2025年,Python已成為金融分析的核心工具: 數據處理效率:Pandas處理百萬行金融數據僅需2.3秒 策略回測速度:Backtrader框架使策略驗證效率提升17倍 風險評估精…

MySQL 從入門到實戰:全方位指南(附 Java 操作示例)

MySQL 入門全方位指南&#xff08;附Java操作示例&#xff09; MySQL 作為最流行的關系型數據庫之一&#xff0c;廣泛應用于各類應用開發中。本文將從安裝開始&#xff0c;逐步講解 MySQL 的核心知識點與操作技巧&#xff0c;并通過 Java 示例展示客戶端交互&#xff0c;幫助你…

從低空感知邁向智能協同網絡:構建智能空域的“視頻基礎設施”

?? 引言&#xff1a;低空經濟起飛&#xff0c;智能視覺鏈路成剛需基建 隨著政策逐步開放與技術加速成熟&#xff0c;低空經濟正從概念走向全面起飛。從載人 eVTOL 到物流無人機&#xff0c;從空中巡檢機器人到城市立體交通調度平臺&#xff0c;低空場景正在成為繼地面交通和…

Node.js- express的基本使用

Express 核心概念? Express是基于Node.js的輕量級Web框架&#xff0c;封裝了HTTP服務、路由管理、中間件等核心功能&#xff0c;簡化了Web應用和API開發 核心優勢?? 中間件架構&#xff1a;支持模塊化請求處理流程路由系統&#xff1a;直觀的URL到處理函數的映射高性能&…

計算機網絡:網絡號和網絡地址的區別

在計算機網絡中&#xff0c;“網絡號”和“網絡地址”是兩個密切相關但含義不同的概念&#xff0c;主要用于IP地址的劃分和網絡標識。以下從定義、作用、關聯與區別等方面詳細說明&#xff1a; 1. 網絡號&#xff08;Network Number&#xff09;定義&#xff1a;網絡號是IP地址…

【iOS】3GShare仿寫

【iOS】3GShare仿寫 文章目錄【iOS】3GShare仿寫登陸注冊界面主頁搜索文章活動我的總結登陸注冊界面 這個界面的ui東西不多&#xff0c;主要就是幾個輸入框及對輸入內容的一些判斷 登陸界面 //這里設置了一個初始密碼并儲存到NSUserDefaults中 NSUserDefaults *defaults [N…

從案例學習cuda編程——線程模型和顯存模型

1. cuda介紹CUDA&#xff08;Compute Unified Device Architecture&#xff0c;統一計算設備架構&#xff09;是NVIDIA推出的一種并行計算平臺和編程模型。它允許開發者利用NVIDIA GPU的強大計算能力來加速計算密集型任務。CUDA通過提供一套專門的API和編程接口&#xff0c;使得…