【Go語言圣經2.5】

目標

了解類型定義不僅告訴編譯器如何在內存中存儲和處理數據,還對程序設計產生深遠影響:

  • 內存結構:類型決定了變量的底層存儲(比如占用多少字節、內存布局等)。
  • 操作符與方法集:類型決定了哪些內置運算符適用于它,以及能否為該類型定義方法,從而擴展它的行為。
  • 語義區分:通過定義新類型,即使它們的底層類型相同,也能明確區分不同概念,避免混用(例如溫度單位、索引、文件描述符等)。
  • 可讀性與安全性:使用命名類型可以讓代碼語義更明確,從而降低出錯的風險。

概念

  1. 每個變量或表達式都有一個類型,類型描述了值的屬性,如數據占用的內存大小、內部結構、支持哪些操作以及關聯的方法集等。
  2. 一個 int 類型的變量可能用于表示索引、時間戳或月份;一個 float64 類型的變量可能表示速度或溫度。盡管底層都是數字,但語義上卻截然不同。
  3. 內存與數據表示:每個數據類型在內存中的表示方式(如整數占用 32 位或 64 位)由其底層類型決定。命名類型會沿用相同的存儲方式,但在類型系統中賦予它新的含義。
  4. 方法與接收者
    • **方法的定義:**在 Go 中,可以為任意命名類型定義方法,使得該類型的值具有特定行為(如格式化輸出)。
    • 調用示例:fmt.Printf 等函數會自動調用類型的 String 方法,從而定制輸出格式。
    • 靜態分派:fmt.Printf 等函數會自動調用類型的 String 方法,從而定制輸出格式。

要點

類型聲明語句

type 新類型名稱 底層類型

這條語句創建一個新的類型名稱,其底層結構與現有類型相同,但在類型系統中被認為是不同的。例如:

type Celsius float64    // 攝氏溫度類型
type Fahrenheit float64 // 華氏溫度類型

即使 Celsius 和 Fahrenheit 都基于 float64,它們是兩個不同的類型,防止你無意中混用不同溫度單位的數據。

  • 命名規則與導出
    • 如果新類型名稱的首字符大寫,則表示該類型對包外可見(導出)。
    • Go 語言中關于 Unicode 字母的規則也使得中文命名默認不能導出(Go 1 的規則),但在將來的 Go 2 中可能會調整。
  • 用途
    • 語義區分:通過定義不同的命名類型(即使底層相同)可以讓程序更安全,不會將代表不同概念的值誤用在一起。
    • 簡化代碼:對于復雜或冗長的類型,用一個簡單的名稱可以使代碼更清晰易讀。

類型轉換操作

  1. 操作形式

    類型轉換寫作 T(x),它不會改變 x 的實際值,只是將它“貼上”新的類型標簽

    var f Fahrenheit = CToF(BoilingC)
    fmt.Println(Celsius(f)) // 將 f 轉換為 Celsius 類型
    
    • 限制:只有當兩個類型的底層類型完全相同時,或者都是指向相同底層結構的指針時,才能進行轉換。
  2. 作用

    通過類型轉換,可以將同樣底層數據但語義不同的值顯式轉換,使得運算和比較變得類型安全。例如

    var c Celsius
    var f Fahrenheit
    // c == f // 編譯錯誤:類型不匹配
    fmt.Println(c == Celsius(f)) // 顯式轉換后可以比較
    

類型與方法

  1. 方法集

    命名類型不僅是一個新的數據類型,還可以為該類型定義方法,這使得它擁有特定的行為。

    func (c Celsius) String() string {return fmt.Sprintf("%g°C", c)
    }
    

    這段代碼為 Celsius 類型定義了一個 String 方法,在調用 fmt.Printf 時會自動調用該方法來格式化輸出。(因為 fmt 包會自動調用 String 方法)(具體一點說:當一個類型實現了 String() string 方法后,它就滿足了 fmt 包定義的 Stringer 接口。fmt 包在格式化輸出時,會檢查傳入的值是否實現了該接口,如果實現了,就自動調用 String() 方法來獲取該值的字符串表示。)

    c := FToC(212.0)
    fmt.Println(c.String()) // 輸出 "100°C"
    fmt.Printf("%v\n", c)   // 也輸出 "100°C",因為 fmt 包會自動調用 String 方法

    為類型定義方法不僅增加了代碼的可讀性,也讓類型更具語義。

如何定義 Celsius 與 Fahrenheit 兩個命名類型及它們之間的轉換和方法

// Package tempconv performs Celsius and Fahrenheit temperature computations.
package tempconvimport "fmt"type Celsius float64    // 定義攝氏溫度類型
type Fahrenheit float64 // 定義華氏溫度類型// 常量聲明
const (AbsoluteZeroC Celsius = -273.15 // 絕對零度(攝氏)FreezingC     Celsius = 0       // 冰點(攝氏)BoilingC      Celsius = 100     // 沸點(攝氏)
)// CToF 將攝氏溫度轉換為華氏溫度
func CToF(c Celsius) Fahrenheit { return Fahrenheit(c*9/5 + 32) 
}// FToC 將華氏溫度轉換為攝氏溫度
func FToC(f Fahrenheit) Celsius { return Celsius((f - 32) * 5 / 9) 
}// Celsius 的 String 方法,使其輸出更友好
func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) 
}
  • Celsius 類型的 String 方法為其提供了定制格式,當使用 fmt 包打印時,會自動調用此方法。

類型比較與運算

  • 支持內置運算符

    因為 Celsius 和 Fahrenheit 的底層類型都是 float64,所以它們可以使用底層類型的算術和比較運算符。例如:

    
    fmt.Printf("%g\n", BoilingC-FreezingC) // 輸出 "100"
    boilingF := CToF(BoilingC)
    fmt.Printf("%g\n", boilingF-CToF(FreezingC)) // 輸出 "180"
    

    注意,直接將 Fahrenheit 與 Celsius 進行運算會導致編譯錯誤,因為它們是不同的命名類型。

  • 比較運算

    只有相同類型之間才能進行直接比較:

    var c Celsius
    var f Fahrenheit
    fmt.Println(c == 0)          // "true",0 會被視為 Celsius 類型的零值
    fmt.Println(f >= 0)          // "true",同理,0 對于 Fahrenheit 也是零值
    // fmt.Println(c == f)       // 編譯錯誤:類型不匹配
    fmt.Println(c == Celsius(f)) // 正確:通過類型轉換后比較
    

總結

  1. 類型定義描述了變量的內存表示、支持的運算符和方法集,同時區分不同的語義。
  2. 將不同的概念定義為不同的命名類型,即使它們底層相同,也能在編譯期防止錯誤的混用。(例如,不小心將溫度與文件描述符混用可能引發錯誤,通過定義不同類型就可以避免這種情況。)
  3. 類型轉換 T(x) 只改變 x 的類型標簽而不改變底層數據。轉換要求兩個類型有相同的底層類型或兼容的結構。
  4. 方法與類型行為:為命名類型定義方法(如 String 方法),使得在打印和其它操作時可以自動調用,增強了類型的表現力。
  5. 新類型繼承了底層類型的算術與比較操作,但必須保證操作數類型一致。

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

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

相關文章

IDEA 一鍵完成:打包 + 推送 + 部署docker鏡像

1、本方案要解決場景? 想直接通過本地 IDEA 將最新的代碼部署到遠程服務器上。 2、本方案適用于什么樣的項目? 項目是一個 Spring Boot 的 Java 項目。項目用 maven 進行管理。項目的運行基于 docker 容器(即項目將被打成 docker image&am…

SpringBoot 第一課(Ⅲ) 配置類注解

目錄 一、PropertySource 二、ImportResource ①SpringConfig (Spring框架全注解) ②ImportResource注解實現 三、Bean 四、多配置文件 多Profile文件的使用 文件命名約定: 激活Profile: YAML文件支持多文檔塊&#xff…

深度解析React Native底層核心架構

React Native 工作原理深度解析 一、核心架構:三層異構協作體系 React Native 的跨平臺能力源于其獨特的 JS層-Shadow層-Native層 架構設計,三者在不同線程中協同工作: JS層 運行于JavaScriptCore(iOS)或Hermes&…

對話智能體的正確打開方式:解析主流AI聊天工具的核心能力與使用方式

一、人機對話的黃金法則 在與人工智能對話系統交互時,掌握以下七項核心原則可顯著提升溝通效率:文末有教程分享地址 意圖精準表達術 采用"背景需求限定條件"的結構化表達 示例優化:"請用Python編寫一個網絡爬蟲&#xff08…

Xinference大模型配置介紹并通過git-lfs、hf-mirror安裝

文章目錄 一、Xinference開機服務systemd二、語言(LLM)模型2.1 配置介紹2.2 DeepSeek-R1-Distill-Qwen-32B(大杯)工具下載git-lfs(可以繞過Hugging Face) 2.3 DeepSeek-R1-Distill-Qwen-32B-Q4_K_M-GGUF&am…

MyBatis操縱數據庫-XML實現(補充)

目錄 一.多表查詢二.MyBatis參數賦值(#{ }和${ })2.1 #{ }和${ }的使用2.2 #{ }和${ }的區別2.3 SQL注入2.3 ${ }的應用場景2.3.1 排序功能2.3.2 like查詢 一.多表查詢 多表查詢的操作和單表查詢基本相同,只需改變一下SQL語句,同時也要在實體類中創建出…

快速導出接口設計表——基于DOMParser的Swagger接口詳情半自動化提取方法

作者聲明:不想看作者聲明的(需要生成接口設計表的)直接前往https://capujin.github.io/A2T/。 注:Github Pages生成的頁面可能會出現訪問不穩定,暫時沒將源碼上傳至Github,如有需要,可聯系我私…

TS常見內置映射類型的實現及應用場景

以下是 TypeScript 在前端項目中 常用的映射類型&#xff08;Mapped Types&#xff09;&#xff0c;結合具體場景和代碼示例&#xff0c;幫助開發者高效處理復雜類型&#xff1a; 一、基礎映射類型 1. Partial<T> 作用&#xff1a;將對象類型 T 的所有屬性變為可選。 實…

介紹如何使用YOLOv8模型進行基于深度學習的吸煙行為檢測

下面為你詳細介紹如何使用YOLOv8模型進行基于深度學習的吸煙行為檢測&#xff0c;包含環境配置、數據準備、模型訓練以及推理等步驟。 1. 環境配置 首先&#xff0c;你需要安裝必要的庫&#xff0c;主要是ultralytics庫&#xff0c;它包含了YOLOv8模型。你可以使用以下命令進…

AI-醫學影像分割方法與流程

AI醫學影像分割方法與流程–基于低場磁共振影像的病灶識別 – 作者:coder_fang AI框架&#xff1a;PaddleSeg 數據準備&#xff0c;使用MedicalLabelMe進行dcm文件標注&#xff0c;產生同名.json文件。 編寫程序生成訓練集圖片&#xff0c;包括掩碼圖。 代碼如下: def doC…

【Python】09、字典

文章目錄 1. 字典簡介2. 字典的使用2.1 字典創建2.2 字典值獲取2.3 字典值修改2.4 字典的刪除 3. 字典的遍歷 1. 字典簡介 字典(dict)屬于一種新的數據結構&#xff0c;稱為映射(mapping)。 字典的作用和列表類似&#xff0c;但是查詢性能比列表好&#xff1b;在字典中每個元…

【貪心算法4】

力扣452.用最少數量的剪引爆氣球 鏈接: link 思路 這道題的第一想法就是如果氣球重疊得越多那么用箭越少&#xff0c;所以先將氣球按照開始坐標從小到大排序&#xff0c;遇到有重疊的氣球&#xff0c;在重疊區域右邊界最小值之前的區域一定需要一支箭&#xff0c;這道題有兩…

SGMEA: Structure-Guided Multimodal Entity Alignment

3 Method 3.1 Problem Definition 3.2 Framework Description 總體框架如圖2所示&#xff0c;由三個主要部分組成&#xff1a;初始嵌入采集模塊、結構引導模塊和模態融合模塊。 3.3 Initial Embedding Acquisition 3.3.1 Structural Embedding 3.3.2 Relation, Attribute, …

KY-038 聲音傳感器如何工作以及如何將其與 ESP32 連接

想為您的項目賦予聲音感!然后跟著做,因為在這個項目中,我們將連接一個聲音傳感器,用它構建一些有趣的項目。我們使用的 KY-038 聲音傳感器使用電容式麥克風來檢測聲波,這為我們提供了穩定性和可靠性的完美平衡。因此,在本文中,我們決定將 KY-038 傳感器與 ESP32 連接,并…

《基于超高頻RFID的圖書館管理系統的設計與實現》開題報告

一、研究背景與意義 1.研究背景 隨著信息化時代的到來&#xff0c;運用計算機科學技術實現圖書館的管理工作已成為優勢。更加科學地管理圖書館會大大提高工作效率。我國的圖書管理體系發展經歷了三個階段&#xff1a;傳統圖書管理模式、現代圖書管理模式以及基于無線射頻識別&…

[local-file-system]基于服務器磁盤的本地文件存儲方案

[local-file-system]基于服務器磁盤的本地文件存儲方案 僅提供后端方案 github 環境 JDK11linux/windows/mac 應用場景 適用于ToB業務&#xff0c;中小企業的單體服務&#xff0c;僅使用磁盤存儲文件的解決方案 僅使用服務器磁盤存儲 與業務實體相結合的文件存儲方案&…

P5708 【深基2.習2】三角形面積(洛谷—python)

題目描述 一個三角形的三邊長分別是 a、b、c&#xff0c;那么它的面積為 p(p?a)(p?b)(p?c)?&#xff0c;其中 p21?(abc)。輸入這三個數字&#xff0c;計算三角形的面積&#xff0c;四舍五入精確到 1 位小數。 輸入格式 第一行輸入三個實數 a,b,c&#xff0c;以空格隔開…

智慧加油站小程序數據庫設計文檔

智慧加油站系統 - 數據庫與API設計文檔 1. 數據庫設計 1.1 ER模型 系統的核心實體關系如下&#xff1a; 用戶(User) ---< 訂單(Order) ---< 加油記錄(RefuelRecord)| | || | vv v …

C++博客分享

本周的一些 C視頻分享, 或許后續會做一些內容總結. 博客 Polymorphic, Defaulted EqualityConstexpr factors_ofC26: Removing language featuresBypassing the branch predictor Meeting C 2024 Clean CMake for C (library) developers - Kerstin KellerAn Introduction …

【藍橋杯每日一題】3.16

&#x1f3dd;?專欄&#xff1a; 【藍橋杯備篇】 &#x1f305;主頁&#xff1a; f狐o貍x 目錄 3.9 高精度算法 一、高精度加法 題目鏈接&#xff1a; 題目描述&#xff1a; 解題思路&#xff1a; 解題代碼&#xff1a; 二、高精度減法 題目鏈接&#xff1a; 題目描述&…