Golang 知識點總結
本文是由TapirLiu總結的Golang中的一些知識點,對于深入學習Golang很有幫助,所以我特意翻譯了一下。
各種類型復制的時候的花費
本節標題也可以叫做“各種類型的值的大小” (the sizes of values of all kinds of types),底層可被不同的值共享的數據的大小未被計算。
下面的表格中一個word在32bit操作系統中代表4個字節,在64bit操作系統中代表8個字節,內容基于官方的Go 1.7的編譯器。
Type | Cost Of Value Copying (Value Size) |
---|---|
bool | 1 byte |
int8, uint8, byte | 1 byte |
int16, uint16 | 2 bytes |
int32, uint32, rune | 4 bytes |
int64, uint64 | 8 bytes |
int, uint, uintptr | 1 word |
string | 2 words |
pointer | 1 word |
slice | 3 words |
map | 1 word |
channel | 1 word |
function | 1 word |
interface | 2 words |
struct | the sum of sizes of all fields |
array | (element value size) * (array length) |
可使用內建函數的類型 (len、cap、close、delete、make)
len | cap | close | delete | make | |
---|---|---|---|---|---|
string | Yes | ||||
array (and array pointer) | Yes | Yes | |||
slice | Yes | Yes | Yes | ||
map | Yes | Yes | Yes | ||
channel | Yes | Yes | Yes | Yes |
上面的所有類型都可以使用range遍歷。
可以用作len函數參數的類型也叫做容器類型。
內建容器類型的值比較
假定容器的值可尋址(addressable)。
Type | 長度可變 | 元素可更新 | 元素可尋址 | 查找會更改容器的長度 | 底層元素可以共享 |
---|---|---|---|---|---|
string | No | No | No | No | Yes |
array | No | Yes | Yes | No | No |
slice | No | Yes | Yes | No | Yes |
map | Yes | Yes | No | No | Yes |
channel | Yes | No | No | Yes | Yes |
組合類型T{...}的值比較
Type (T) | T{}是類型T的零值? |
---|---|
struct | Yes |
array | Yes |
slice | No (零值是nil) |
map | No (零值是nil) |
零值是nil的類型
Type (T) | Size Of T(nil) |
---|---|
pointer | 1 word |
slice | 3 words |
map | 1 word |
channel | 1 word |
function | 1 word |
interface | 2 words |
這些類型的零值的大小和上面類型的大小保持一致。
編譯時被執行的函數
如果函數在編譯時被執行,那么它的返回值是常量。
Function | 返回值 | 編譯時便計算? |
---|---|---|
unsafe.Sizeof | uintptr | Yes, 總是 |
unsafe.Alignof | ||
unsafe.Offsetof | ||
len | int | 有時候是 Go 規范中講到 :
|
cap | ||
real | float64 (默認類型) |
有時候是 Go 規范中講到 : 如果s是復數常量,則real(s)和imag(s)是常量. |
imag | ||
complex | complex128 (默認類型) |
有時候是 Go 規范中講到 : 如果sr和si都是常量,則complex(sr, si)是常量. |
不能被尋址的值
下面的值不能被尋址(addresses):
- bytes in strings:字符串中的字節
- map elements:map中的元素
- dynamic values of interface values (exposed by type assertions):接口的動態值
- constant values:常量
- literal values:字面值
- package level functions:包級別的函數
- methods (used as function values):方法
- intermediate values:中間值
- function callings
- explicit value conversions
- all sorts of operations, except pointer dereference operations, but including:
- channel receive operations
- sub-string operations
- sub-slice operations
- addition, subtraction, multiplication, and division, etc.
注意,&T{}相當于tmp := T{}; (&tmp)的語法糖,所以&T{}可合法不意味著T{}可尋址。
下面的值可以尋址:
- variables
- fields of addressable structs
- elements of addressable arrays
- elements of any slices (whether the slices are addressable or not)
- pointer dereference operations
不支持比較的類型
下面的類型不支持直接比較:
- map
- slice
- function
- struct types containing incomparable fields
- array types with incomparable elements
這些不能直接比較的類型不能用做map的key值。
注意:盡管map、slice、function類型不支持直接比較,但是它們的值卻可以和nil直接比較。如果兩個接口的動態類型不能比較,運行時比較這兩個接口會panic,除非其中一個的動態值是untyped nil。
可命名的源代碼元素
下面的源代碼元素可以命名,名稱必須是 Identifier
可以使用_做名稱? | |
---|---|
package | No |
import | Yes |
type | Yes |
variable | Yes |
constant | Yes |
function | Yes |
label | Yes |
命名的源代碼元素可以使用()分組聲明
下面的類型可以使用()分組生命
- import
- type
- variable
- constant
函數和標簽(label)不能使用()分組聲明。
可以在函數內外聲明的源代碼元素
下面的類型可以聲明在函數內,也可以聲明在函數外:
- type
- variable
- constant
import必須在其它元素的聲明的前面(package語句的后面)。
函數在其它函數的外面聲明。(譯者注:函數變量/匿名函數可以在函數內聲明)
標簽(label)必須聲明在函數內。
可以返回一個可選bool返回值的表達式
下面的表達式可以返回一個可選的bool值:
可選的bool返回值的意義 | 忽略可選值會影響程序的行為? | |
---|---|---|
map element access | map中是否包含要 | No |
channel value receive | 在channel關閉前收到的值是否已發出 | No |
type assertion | 接口的動態類型是否符合asserted type | Yes |
(當可選值被忽略時,如果類型不match則會拋出panic)|
使用channel機制永遠阻塞當前goroutine的方法
下面的方法都可以永遠阻塞當前的goroutine:
1、receive from a channel which no values will be sent to
<-make(chan struct{}) // or<-make(<-chan struct{})
2、send value to a channel which no ones will receive values from
make(chan struct{}) <- struct{}{}// ormake(chan<- struct{}) <- struct{}{}
3、receive value from a nil channel
<-chan struct{}(nil)
4、send value to a nil channel
chan struct{}(nil) <- struct{}{}
5、use a bare select block
select{}
連接字符串的幾種方法
下面幾種方法都可以連接字符串(譯者注:不考慮性能):
1、使用+連接字符串。如果連接的字符串少于6個,官方的編譯器會對此優化,所以通常使用+簡便而有效。
2、使用strings包中的 strings.Join 連接字符串。
3、使用fmt包中的fmt.Sprintf,fmt.Sprint和fmt.Sprintln連接字符串。這三個方法可以將任意的類型連接成字符串。fmt.Sprintln會在字符串之間加空格,在字符串尾部加新的換行符。如果兩個值中的至少一個不是字符串,fmt.Sprint會在它們之間加空格。
4、包bytes的Buffer類型(或者內建函數copy)可以用來構建 byte slice, byte slice可以方便地轉換成字符串。
來自:http://www.udpwork.com/item/16086.html