Go Quiz: 從Go面試題看數值型別的自動推導

coding進階 發表於 2022-06-05
面試 Go

背景

Google工程師Valentin Deleplace出了幾道關於Go數值型別的計算題,很有迷惑性,整體正確率不到50%,拿出來和大家分享下。

題目1

var y = 5.2
const z = 2
fmt.Println(y / z)
  • A: 2.6
  • B: 2.5
  • C: 2
  • D: 編譯錯誤

題目2

const a = 7.0
var b = 2
fmt.Println(a / b)
  • A: 3.5
  • B: 3
  • C: 編譯錯誤

題目3

a := 40
f := float64(a/100.0)
fmt.Println(f)
  • A: 0
  • B: 0.4
  • C: 編譯錯誤

解析

這道題主要考察3個知識點:

  • 對於變數而言,如果沒有顯示指定資料型別,編譯器會根據賦值自動推匯出確定的資料型別。

    整數的預設型別是int,浮點數的預設型別是float64,官方說明如下:

    An untyped constant has a default type which is the type to which the constant is implicitly converted in contexts where a typed value is required, for instance, in a short variable declaration such as i := 0 where there is no explicit type. The default type of an untyped constant is bool, rune, int, float64, complex128 or string respectively, depending on whether it is a boolean, rune, integer, floating-point, complex, or string constant.
  • 對於常量而言,如果沒有顯示指定資料型別,編譯器同樣會推匯出一個資料型別,但是沒有顯示指定資料型別的常量在程式碼上下文裡可以根據需要隱式轉化為需要的資料型別進行計算
  • Go不允許不同的資料型別做運算。當變數和沒有顯示指定資料型別的常量混合在一起運算時,如果常量轉化成變數的型別不會損失精度,那常量會自動轉化為變數的資料型別參與運算。如果常量轉化成變數的型別會損失精度,那就會編譯報錯。

對於題目1:變數y 沒有顯示指定資料型別,但是根據後面的賦值5.2,編譯器自動推匯出變數y的資料型別是float64。常量z沒有顯示指定資料型別,編譯器自動推匯出的型別是int,但是在運算y/z時,因為y是float64型別,z轉化為float64型別不會損失精度,所以z在運算時會自動轉換為float64型別,所以本題的運算結果是2.6,答案是A

對於題目2:變數b沒有顯示指定資料型別,根據後面的賦值2,編譯器自動推匯出變數b的資料型別是int。常量a沒有顯示指定資料型別,編譯器自動推匯出的型別是float64,但是在運算a/b時,因為b是int型別,a轉換為int型別不會損失精度,所以a在運算時會自動轉換為int型別參與計算,所以本題的結果是7/2,結果是3,答案是B

對於題目3:變數a沒有顯示指定資料型別,根據後面的賦值40,編譯器自動推匯出變數a的資料型別是int。常量100.0沒有顯示指定資料型別,編譯器自動推匯出的型別是float64,但是在運算a/100.0時,因為a是int型別,100.0轉換為int型別不會損失精度,所以100.0在運算時會自動轉換為int型別參與計算,所以本題的結果是40/100,結果是0,答案是A

思考題

題目1:

var (
    a = 1.0
    b = 2
)
fmt.Println(a / b)

題目2:

const (
    x = 5.0
    y = 4
)
fmt.Println(x / y)

題目3:

const t = 4.8
var u = 2
fmt.Println(t / u)

想知道答案的可以給公眾號傳送訊息data獲取答案。

總結

  • 對於未指定資料型別的變數,編譯器會自動推匯出預設的資料型別,在參與運算時,變數始終用這個推匯出來的資料型別參與運算,不會做任何隱式型別轉換。
  • 對於未指定資料型別的常量,編譯器雖然也會自動推匯出預設的資料型別,但是在參與運算時,常量可以根據程式碼的上下文,自動隱式轉換為所需要的資料型別,只要不出現精度丟失即可。如果出現精度丟失,那就會編譯報錯。

開源地址

文章和示例程式碼開源在GitHub: Go語言初級、中級和高階教程

公眾號:coding進階。關注公眾號可以獲取最新Go面試題和技術棧。

個人網站:Jincheng's Blog

知乎:無忌

References