mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2025-12-08 17:31:37 +00:00
fmt
This commit is contained in:
@@ -87,4 +87,4 @@ fmt.Println(geometry.PathDistance(perim)) // "12", standalone function
|
||||
fmt.Println(perim.Distance()) // "12", method of geometry.Path
|
||||
```
|
||||
|
||||
譯註:如果我們要用方法去計算perim的distance,還需要去寫全geometry的包名,和其函數名,但是因爲Path這個變量定義了一個可以直接用的Distance方法,所以我們可以直接寫perim.Distance()。相當於可以少打很多字,作者應該是這個意思。因爲在Go里包外調用函數需要帶上包名,還是挺麻煩的。
|
||||
**譯註:** 如果我們要用方法去計算perim的distance,還需要去寫全geometry的包名,和其函數名,但是因爲Path這個變量定義了一個可以直接用的Distance方法,所以我們可以直接寫perim.Distance()。相當於可以少打很多字,作者應該是這個意思。因爲在Go里包外調用函數需要帶上包名,還是挺麻煩的。
|
||||
|
||||
@@ -63,4 +63,4 @@ m.Add("item", "3") // panic: assignment to entry in nil map
|
||||
|
||||
對Get的最後一次調用中,nil接收器的行爲卽是一個空map的行爲。我們可以等價地將這個操作寫成Value(nil).Get("item"),但是如果你直接寫nil.Get("item")的話是無法通過編譯的,因爲nil的字面量編譯器無法判斷其準備類型。所以相比之下,最後的那行m.Add的調用就會産生一個panic,因爲他嚐試更新一個空map。
|
||||
|
||||
由於url.Values是一個map類型,併且間接引用了其key/value對,因此url.Values.Add對這個map里的元素做任何的更新、刪除操作對調用方都是可見的。實際上,就像在普通函數中一樣,雖然可以通過引用來操作內部值,但在方法想要脩改引用本身是不會影響原始值的,比如把他置爲nil,或者讓這個引用指向了其它的對象,調用方都不會受影響。(譯註:因爲傳入的是存儲了內存地址的變量,你改變這個變量是影響不了原始的變量的,想想C語言,是差不多的)
|
||||
由於url.Values是一個map類型,併且間接引用了其key/value對,因此url.Values.Add對這個map里的元素做任何的更新、刪除操作對調用方都是可見的。實際上,就像在普通函數中一樣,雖然可以通過引用來操作內部值,但在方法想要脩改引用本身是不會影響原始值的,比如把他置爲nil,或者讓這個引用指向了其它的對象,調用方都不會受影響。(譯註:因爲傳入的是存儲了內存地址的變量,你改變這個變量是影響不了原始的變量的,想想C語言,是差不多的)
|
||||
|
||||
@@ -85,9 +85,9 @@ pptr.Distance(q) // implicit (*pptr)
|
||||
|
||||
如果類型T的所有方法都是用T類型自己來做接收器(而不是`*T`),那麽拷貝這種類型的實例就是安全的;調用他的任何一個方法也就會産生一個值的拷貝。比如time.Duration的這個類型,在調用其方法時就會被全部拷貝一份,包括在作爲參數傳入函數的時候。但是如果一個方法使用指針作爲接收器,你需要避免對其進行拷貝,因爲這樣可能會破壞掉該類型內部的不變性。比如你對bytes.Buffer對象進行了拷貝,那麽可能會引起原始對象和拷貝對象隻是别名而已,但實際上其指向的對象是一致的。緊接着對拷貝後的變量進行脩改可能會有讓你意外的結果。
|
||||
|
||||
譯註:作者這里説的比較繞,其實有兩點:
|
||||
**譯註:** 作者這里説的比較繞,其實有兩點:
|
||||
|
||||
1.不管你的method的receiver是指針類型還是非指針類型,都是可以通過指針/非指針類型進行調用的,編譯器會幫你做類型轉換
|
||||
2.在聲明一個method的receiver該是指針還是非指針類型時,你需要考慮兩方面的內部,第一方面是這個對象本身是不是特别大,如果聲明爲非指針變量時,調用會産生一次拷貝;第二方面是如果你用指針類型作爲receiver,那麽你一定要註意,這種指針類型指向的始終是一塊內存地址,就算你對其進行了拷貝。熟悉C或者C艹的人這里應該很快能明白。
|
||||
1. 不管你的method的receiver是指針類型還是非指針類型,都是可以通過指針/非指針類型進行調用的,編譯器會幫你做類型轉換。
|
||||
2. 在聲明一個method的receiver該是指針還是非指針類型時,你需要考慮兩方面的內部,第一方面是這個對象本身是不是特别大,如果聲明爲非指針變量時,調用會産生一次拷貝;第二方面是如果你用指針類型作爲receiver,那麽你一定要註意,這種指針類型指向的始終是一塊內存地址,就算你對其進行了拷貝。熟悉C或者C艹的人這里應該很快能明白。
|
||||
|
||||
{% include "./ch6-02-1.md" %}
|
||||
|
||||
@@ -105,9 +105,9 @@ func (*IntSet) Clear() // remove all elements from the set
|
||||
func (*IntSet) Copy() *IntSet // return a copy of the set
|
||||
```
|
||||
|
||||
練習6.2: 定義一個變參方法(*IntSet).AddAll(...int),這個方法可以爲一組IntSet值求和,比如s.AddAll(1,2,3)。
|
||||
**練習 6.2:** 定義一個變參方法(*IntSet).AddAll(...int),這個方法可以爲一組IntSet值求和,比如s.AddAll(1,2,3)。
|
||||
|
||||
練習6.3: (*IntSet).UnionWith會用|操作符計算兩個集合的交集,我們再爲IntSet實現另外的幾個函數IntersectWith(交集:元素在A集合B集合均出現),DifferenceWith(差集:元素出現在A集合,未出現在B集合),SymmetricDifference(併差集:元素出現在A但沒有出現在B,或者出現在B沒有出現在A)。
|
||||
**練習 6.3:** (*IntSet).UnionWith會用|操作符計算兩個集合的交集,我們再爲IntSet實現另外的幾個函數IntersectWith(交集:元素在A集合B集合均出現),DifferenceWith(差集:元素出現在A集合,未出現在B集合),SymmetricDifference(併差集:元素出現在A但沒有出現在B,或者出現在B沒有出現在A)。
|
||||
練習6.4: 實現一個Elems方法,返迴集合中的所有元素,用於做一些range之類的遍歷操作。
|
||||
|
||||
練習6.5: 我們這章定義的IntSet里的每個字都是用的uint64類型,但是64位的數值可能在32位的平台上不高效。脩改程序,使其使用uint類型,這種類型對於32位平台來説更合適。當然了,這里我們可以不用簡單粗暴地除64,可以定義一個常量來決定是用32還是64,這里你可能會用到平台的自動判斷的一個智能表達式:32 << (^uint(0) >> 63)
|
||||
**練習 6.5:** 我們這章定義的IntSet里的每個字都是用的uint64類型,但是64位的數值可能在32位的平台上不高效。脩改程序,使其使用uint類型,這種類型對於32位平台來説更合適。當然了,這里我們可以不用簡單粗暴地除64,可以定義一個常量來決定是用32還是64,這里你可能會用到平台的自動判斷的一個智能表達式:32 << (^uint(0) >> 63)
|
||||
|
||||
Reference in New Issue
Block a user