<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ## 2.5. 類型 變量或表達式的類型定義了對應存儲值的屬性特征,例如數值在內存的存儲大小(或者是元素的bit個數),它們在內部是如何表達的,是否支持一些操作符,以及它們自己關聯的方法集等。 在任何程序中都會存在一些變量有著相同的內部結構,但是卻表示完全不同的概念。例如,一個int類型的變量可以用來表示一個循環的迭代索引、或者一個時間戳、或者一個文件描述符、或者一個月份;一個float64類型的變量可以用來表示每秒移動幾米的速度、或者是不同溫度單位下的溫度;一個字符串可以用來表示一個密碼或者一個顏色的名稱。 一個類型聲明語句創建了一個新的類型名稱,和現有類型具有相同的底層結構。新命名的類型提供了一個方法,用來分隔不同概念的類型,這樣即使它們底層類型相同也是不兼容的。 ```Go type 類型名字 底層類型 ``` 類型聲明語句一般出現在包一級,因此如果新創建的類型名字的首字符大寫,則在包外部也可以使用。 譯注:對于中文漢字,Unicode標志都作為小寫字母處理,因此中文的命名默認不能導出;不過國內的用戶針對該問題提出了不同的看法,根據RobPike的回復,在Go2中有可能會將中日韓等字符當作大寫字母處理。下面是RobPik在 [Issue763](https://github.com/golang/go/issues/5763) 的回復: > A solution that's been kicking around for a while: > > For Go 2 (can't do it before then): Change the definition to “lower case letters and _ are package-local; all else is exported”. Then with non-cased languages, such as Japanese, we can write 日本語 for an exported name and _日本語 for a local name. This rule has no effect, relative to the Go 1 rule, with cased languages. They behave exactly the same. 為了說明類型聲明,我們將不同溫度單位分別定義為不同的類型: <u><i>gopl.io/ch2/tempconv0</i></u> ```Go // Package tempconv performs Celsius and Fahrenheit temperature computations. package tempconv import "fmt" type Celsius float64 // 攝氏溫度 type Fahrenheit float64 // 華氏溫度 const ( AbsoluteZeroC Celsius = -273.15 // 絕對零度 FreezingC Celsius = 0 // 結冰點溫度 BoilingC Celsius = 100 // 沸水溫度 ) func CToF(c Celsius) Fahrenheit { return Fahrenheit(c*9/5 + 32) } func FToC(f Fahrenheit) Celsius { return Celsius((f - 32) * 5 / 9) } ``` 我們在這個包聲明了兩種類型:Celsius和Fahrenheit分別對應不同的溫度單位。它們雖然有著相同的底層類型float64,但是它們是不同的數據類型,因此它們不可以被相互比較或混在一個表達式運算。刻意區分類型,可以避免一些像無意中使用不同單位的溫度混合計算導致的錯誤;因此需要一個類似Celsius(t)或Fahrenheit(t)形式的顯式轉型操作才能將float64轉為對應的類型。Celsius(t)和Fahrenheit(t)是類型轉換操作,它們并不是函數調用。類型轉換不會改變值本身,但是會使它們的語義發生變化。另一方面,CToF和FToC兩個函數則是對不同溫度單位下的溫度進行換算,它們會返回不同的值。 對于每一個類型T,都有一個對應的類型轉換操作T(x),用于將x轉為T類型(譯注:如果T是指針類型,可能會需要用小括弧包裝T,比如`(*int)(0)`)。只有當兩個類型的底層基礎類型相同時,才允許這種轉型操作,或者是兩者都是指向相同底層結構的指針類型,這些轉換只改變類型而不會影響值本身。如果x是可以賦值給T類型的值,那么x必然也可以被轉為T類型,但是一般沒有這個必要。 數值類型之間的轉型也是允許的,并且在字符串和一些特定類型的slice之間也是可以轉換的,在下一章我們會看到這樣的例子。這類轉換可能改變值的表現。例如,將一個浮點數轉為整數將丟棄小數部分,將一個字符串轉為`[]byte`類型的slice將拷貝一個字符串數據的副本。在任何情況下,運行時不會發生轉換失敗的錯誤(譯注: 錯誤只會發生在編譯階段)。 底層數據類型決定了內部結構和表達方式,也決定是否可以像底層類型一樣對內置運算符的支持。這意味著,Celsius和Fahrenheit類型的算術運算行為和底層的float64類型是一樣的,正如我們所期望的那樣。 ```Go fmt.Printf("%g\n", BoilingC-FreezingC) // "100" °C boilingF := CToF(BoilingC) fmt.Printf("%g\n", boilingF-CToF(FreezingC)) // "180" °F fmt.Printf("%g\n", boilingF-FreezingC) // compile error: type mismatch ``` 比較運算符`==`和`<`也可以用來比較一個命名類型的變量和另一個有相同類型的變量,或有著相同底層類型的未命名類型的值之間做比較。但是如果兩個值有著不同的類型,則不能直接進行比較: ```Go var c Celsius var f Fahrenheit fmt.Println(c == 0) // "true" fmt.Println(f >= 0) // "true" fmt.Println(c == f) // compile error: type mismatch fmt.Println(c == Celsius(f)) // "true"! ``` 注意最后那個語句。盡管看起來像函數調用,但是Celsius(f)是類型轉換操作,它并不會改變值,僅僅是改變值的類型而已。測試為真的原因是因為c和g都是零值。 一個命名的類型可以提供書寫方便,特別是可以避免一遍又一遍地書寫復雜類型(譯注:例如用匿名的結構體定義變量)。雖然對于像float64這種簡單的底層類型沒有簡潔很多,但是如果是復雜的類型將會簡潔很多,特別是我們即將討論的結構體類型。 命名類型還可以為該類型的值定義新的行為。這些行為表示為一組關聯到該類型的函數集合,我們稱為類型的方法集。我們將在第六章中討論方法的細節,這里只說些簡單用法。 下面的聲明語句,Celsius類型的參數c出現在了函數名的前面,表示聲明的是Celsius類型的一個名叫String的方法,該方法返回該類型對象c帶著°C溫度單位的字符串: ```Go func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) } ``` 許多類型都會定義一個String方法,因為當使用fmt包的打印方法時,將會優先使用該類型對應的String方法返回的結果打印,我們將在7.1節講述。 ```Go c := FToC(212.0) fmt.Println(c.String()) // "100°C" fmt.Printf("%v\n", c) // "100°C"; no need to call String explicitly fmt.Printf("%s\n", c) // "100°C" fmt.Println(c) // "100°C" fmt.Printf("%g\n", c) // "100"; does not call String fmt.Println(float64(c)) // "100"; does not call String ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看