mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2024-12-25 14:28:58 +00:00
ch6: fix code format
This commit is contained in:
parent
20a8cf71b9
commit
2420954025
@ -4,8 +4,8 @@
|
||||
|
||||
下面來寫我們第一個方法的例子,這個例子在package geometry下:
|
||||
|
||||
<u><i>gopl.io/ch6/geometry</i></u>
|
||||
```go
|
||||
gopl.io/ch6/geometry
|
||||
package geometry
|
||||
|
||||
import "math"
|
||||
@ -14,15 +14,13 @@ type Point struct{ X, Y float64 }
|
||||
|
||||
// traditional function
|
||||
func Distance(p, q Point) float64 {
|
||||
return math.Hypot(q.X-p.X, q.Y-p.Y)
|
||||
return math.Hypot(q.X-p.X, q.Y-p.Y)
|
||||
}
|
||||
|
||||
|
||||
// same thing, but as a method of the Point type
|
||||
func (p Point) Distance(q Point) float64 {
|
||||
return math.Hypot(q.X-p.X, q.Y-p.Y)
|
||||
return math.Hypot(q.X-p.X, q.Y-p.Y)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
上面的代碼里那個附加的參數p,叫做方法的接收器(receiver),早期的面向對象語言留下的遺産將調用一個方法稱爲“向一個對象發送消息”。
|
||||
|
@ -6,15 +6,15 @@
|
||||
// An IntList is a linked list of integers.
|
||||
// A nil *IntList represents the empty list.
|
||||
type IntList struct {
|
||||
Value int
|
||||
Tail *IntList
|
||||
Value int
|
||||
Tail *IntList
|
||||
}
|
||||
// Sum returns the sum of the list elements.
|
||||
func (list *IntList) Sum() int {
|
||||
if list == nil {
|
||||
return 0
|
||||
}
|
||||
return list.Value + list.Tail.Sum()
|
||||
if list == nil {
|
||||
return 0
|
||||
}
|
||||
return list.Value + list.Tail.Sum()
|
||||
}
|
||||
```
|
||||
|
||||
@ -22,8 +22,8 @@ func (list *IntList) Sum() int {
|
||||
|
||||
下面是net/url包里Values類型定義的一部分。
|
||||
|
||||
<u><i>net/url</i></u>
|
||||
```go
|
||||
net/url
|
||||
package url
|
||||
|
||||
// Values maps a string key to a list of values.
|
||||
@ -31,22 +31,22 @@ type Values map[string][]string
|
||||
// Get returns the first value associated with the given key,
|
||||
// or "" if there are none.
|
||||
func (v Values) Get(key string) string {
|
||||
if vs := v[key]; len(vs) > 0 {
|
||||
return vs[0]
|
||||
}
|
||||
return ""
|
||||
if vs := v[key]; len(vs) > 0 {
|
||||
return vs[0]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
// Add adds the value to key.
|
||||
// It appends to any existing values associated with key.
|
||||
func (v Values) Add(key, value string) {
|
||||
v[key] = append(v[key], value)
|
||||
v[key] = append(v[key], value)
|
||||
}
|
||||
```
|
||||
|
||||
這個定義向外部暴露了一個map的類型的變量,併且提供了一些能夠簡單操作這個map的方法。這個map的value字段是一個string的slice,所以這個Values是一個多維map。客戶端使用這個變量的時候可以使用map固有的一些操作(make,切片,m[key]等等),也可以使用這里提供的操作方法,或者兩者併用,都是可以的:
|
||||
|
||||
<u><i>gopl.io/ch6/urlvalues</i></u>
|
||||
```go
|
||||
gopl.io/ch6/urlvalues
|
||||
m := url.Values{"lang": {"en"}} // direct construction
|
||||
m.Add("item", "1")
|
||||
m.Add("item", "2")
|
||||
|
@ -4,8 +4,8 @@
|
||||
|
||||
```go
|
||||
func (p *Point) ScaleBy(factor float64) {
|
||||
p.X *= factor
|
||||
p.Y *= factor
|
||||
p.X *= factor
|
||||
p.Y *= factor
|
||||
}
|
||||
```
|
||||
|
||||
@ -27,6 +27,7 @@ r := &Point{1, 2}
|
||||
r.ScaleBy(2)
|
||||
fmt.Println(*r) // "{2, 4}"
|
||||
```
|
||||
|
||||
或者這樣:
|
||||
|
||||
```go
|
||||
|
@ -2,13 +2,15 @@
|
||||
|
||||
來看看ColoredPoint這個類型:
|
||||
|
||||
<u><i>gopl.io/ch6/coloredpoint</i></u>
|
||||
```go
|
||||
gopl.io/ch6/coloredpoint
|
||||
import "image/color"
|
||||
|
||||
type Point struct{ X, Y float64 }
|
||||
|
||||
type ColoredPoint struct {
|
||||
Point
|
||||
Color color.RGBA
|
||||
Point
|
||||
Color color.RGBA
|
||||
}
|
||||
```
|
||||
|
||||
@ -47,11 +49,11 @@ p.Distance(q) // compile error: cannot use q (ColoredPoint) as Point
|
||||
|
||||
```go
|
||||
func (p ColoredPoint) Distance(q Point) float64 {
|
||||
return p.Point.Distance(q)
|
||||
return p.Point.Distance(q)
|
||||
}
|
||||
|
||||
func (p *ColoredPoint) ScaleBy(factor float64) {
|
||||
p.Point.ScaleBy(factor)
|
||||
p.Point.ScaleBy(factor)
|
||||
}
|
||||
```
|
||||
|
||||
@ -61,8 +63,8 @@ func (p *ColoredPoint) ScaleBy(factor float64) {
|
||||
|
||||
```go
|
||||
type ColoredPoint struct {
|
||||
*Point
|
||||
Color color.RGBA
|
||||
*Point
|
||||
Color color.RGBA
|
||||
}
|
||||
|
||||
p := ColoredPoint{&Point{1, 1}, red}
|
||||
@ -77,10 +79,11 @@ fmt.Println(*p.Point, *q.Point) // "{2 2} {2 2}"
|
||||
|
||||
```go
|
||||
type ColoredPoint struct {
|
||||
Point
|
||||
color.RGBA
|
||||
Point
|
||||
color.RGBA
|
||||
}
|
||||
```
|
||||
|
||||
然後這種類型的值便會擁有Point和RGBA類型的所有方法,以及直接定義在ColoredPoint中的方法。當編譯器解析一個選擇器到方法時,比如p.ScaleBy,它會首先去找直接定義在這個類型里的ScaleBy方法,然後找被ColoredPoint的內嵌字段們引入的方法,然後去找Point和RGBA的內嵌字段引入的方法,然後一直遞歸向下找。如果選擇器有二義性的話編譯器會報錯,比如你在同一級里有兩個同名的方法。
|
||||
|
||||
方法隻能在命名類型(像Point)或者指向類型的指針上定義,但是多虧了內嵌,有些時候我們給匿名struct類型來定義方法也有了手段。
|
||||
@ -89,15 +92,15 @@ type ColoredPoint struct {
|
||||
|
||||
```go
|
||||
var (
|
||||
mu sync.Mutex // guards mapping
|
||||
mapping = make(map[string]string)
|
||||
mu sync.Mutex // guards mapping
|
||||
mapping = make(map[string]string)
|
||||
)
|
||||
|
||||
func Lookup(key string) string {
|
||||
mu.Lock()
|
||||
v := mapping[key]
|
||||
mu.Unlock()
|
||||
return v
|
||||
mu.Lock()
|
||||
v := mapping[key]
|
||||
mu.Unlock()
|
||||
return v
|
||||
}
|
||||
```
|
||||
|
||||
@ -105,18 +108,18 @@ func Lookup(key string) string {
|
||||
|
||||
```go
|
||||
var cache = struct {
|
||||
sync.Mutex
|
||||
mapping map[string]string
|
||||
sync.Mutex
|
||||
mapping map[string]string
|
||||
}{
|
||||
mapping: make(map[string]string),
|
||||
mapping: make(map[string]string),
|
||||
}
|
||||
|
||||
|
||||
func Lookup(key string) string {
|
||||
cache.Lock()
|
||||
v := cache.mapping[key]
|
||||
cache.Unlock()
|
||||
return v
|
||||
cache.Lock()
|
||||
v := cache.mapping[key]
|
||||
cache.Unlock()
|
||||
return v
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -68,15 +68,15 @@ func (p Point) Sub(q Point) Point { return Point{p.X - q.X, p.Y - q.Y} }
|
||||
type Path []Point
|
||||
|
||||
func (path Path) TranslateBy(offset Point, add bool) {
|
||||
var op func(p, q Point) Point
|
||||
if add {
|
||||
op = Point.Add
|
||||
} else {
|
||||
op = Point.Sub
|
||||
}
|
||||
for i := range path {
|
||||
// Call either path[i].Add(offset) or path[i].Sub(offset).
|
||||
path[i] = op(path[i], offset)
|
||||
}
|
||||
var op func(p, q Point) Point
|
||||
if add {
|
||||
op = Point.Add
|
||||
} else {
|
||||
op = Point.Sub
|
||||
}
|
||||
for i := range path {
|
||||
// Call either path[i].Add(offset) or path[i].Sub(offset).
|
||||
path[i] = op(path[i], offset)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -4,38 +4,38 @@ Go語言里的集合一般會用map[T]bool這種形式來表示,T代表元素
|
||||
|
||||
一個bit數組通常會用一個無符號數或者稱之爲“字”的slice或者來表示,每一個元素的每一位都表示集合里的一個值。當集合的第i位被設置時,我們才説這個集合包含元素i。下面的這個程序展示了一個簡單的bit數組類型,併且實現了三個函數來對這個bit數組來進行操作:
|
||||
|
||||
<u><i>gopl.io/ch6/intset</i></u>
|
||||
```go
|
||||
gopl.io/ch6/intset
|
||||
// An IntSet is a set of small non-negative integers.
|
||||
// Its zero value represents the empty set.
|
||||
type IntSet struct {
|
||||
words []uint64
|
||||
words []uint64
|
||||
}
|
||||
|
||||
// Has reports whether the set contains the non-negative value x.
|
||||
func (s *IntSet) Has(x int) bool {
|
||||
word, bit := x/64, uint(x%64)
|
||||
return word < len(s.words) && s.words[word]&(1<<bit) != 0
|
||||
word, bit := x/64, uint(x%64)
|
||||
return word < len(s.words) && s.words[word]&(1<<bit) != 0
|
||||
}
|
||||
|
||||
// Add adds the non-negative value x to the set.
|
||||
func (s *IntSet) Add(x int) {
|
||||
word, bit := x/64, uint(x%64)
|
||||
for word >= len(s.words) {
|
||||
s.words = append(s.words, 0)
|
||||
}
|
||||
s.words[word] |= 1 << bit
|
||||
word, bit := x/64, uint(x%64)
|
||||
for word >= len(s.words) {
|
||||
s.words = append(s.words, 0)
|
||||
}
|
||||
s.words[word] |= 1 << bit
|
||||
}
|
||||
|
||||
// UnionWith sets s to the union of s and t.
|
||||
func (s *IntSet) UnionWith(t *IntSet) {
|
||||
for i, tword := range t.words {
|
||||
if i < len(s.words) {
|
||||
s.words[i] |= tword
|
||||
} else {
|
||||
s.words = append(s.words, tword)
|
||||
}
|
||||
}
|
||||
for i, tword := range t.words {
|
||||
if i < len(s.words) {
|
||||
s.words[i] |= tword
|
||||
} else {
|
||||
s.words = append(s.words, tword)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
@ -46,23 +46,23 @@ func (s *IntSet) UnionWith(t *IntSet) {
|
||||
```go
|
||||
// String returns the set as a string of the form "{1 2 3}".
|
||||
func (s *IntSet) String() string {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteByte('{')
|
||||
for i, word := range s.words {
|
||||
if word == 0 {
|
||||
continue
|
||||
}
|
||||
for j := 0; j < 64; j++ {
|
||||
if word&(1<<uint(j)) != 0 {
|
||||
if buf.Len() > len("{") {
|
||||
buf.WriteByte('}')
|
||||
}
|
||||
fmt.Fprintf(&buf, "%d", 64*i+j)"}")}}
|
||||
}
|
||||
}
|
||||
}
|
||||
buf.WriteByte('}')
|
||||
return buf.String()
|
||||
var buf bytes.Buffer
|
||||
buf.WriteByte('{')
|
||||
for i, word := range s.words {
|
||||
if word == 0 {
|
||||
continue
|
||||
}
|
||||
for j := 0; j < 64; j++ {
|
||||
if word&(1<<uint(j)) != 0 {
|
||||
if buf.Len() > len("{") {
|
||||
buf.WriteByte('}')
|
||||
}
|
||||
fmt.Fprintf(&buf, "%d", 64*i+j)"}")}}
|
||||
}
|
||||
}
|
||||
}
|
||||
buf.WriteByte('}')
|
||||
return buf.String()
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -63,9 +63,9 @@ func (c *Counter) Reset() { c.n = 0 }
|
||||
```go
|
||||
package log
|
||||
type Logger struct {
|
||||
flags int
|
||||
prefix string
|
||||
// ...
|
||||
flags int
|
||||
prefix string
|
||||
// ...
|
||||
}
|
||||
func (l *Logger) Flags() int
|
||||
func (l *Logger) SetFlags(flag int)
|
||||
|
Loading…
Reference in New Issue
Block a user