func (slice ByteSlice) Append(data []byte) []byte { // Body exactly the same as the Append function defined above. l := len(slice) if l+len(data) > cap(slice) { // reallocate // Allocate double what's needed, for future growth. newSlice := make([]byte, (l+len(data))*2) // The copy function is predeclared and works for any slice type. copy(newSlice, slice) slice = newSlice } slice = slice[0 : l+len(data)] copy(slice[l:], data) return slice }
func (p *ByteSlice) Append2(data []byte) { slice := *p // Body as above, without the return. l := len(slice) if l+len(data) > cap(slice) { // reallocate // Allocate double what's needed, for future growth. newSlice := make([]byte, (l+len(data))*2) // The copy function is predeclared and works for any slice type. copy(newSlice, slice) slice = newSlice } slice = slice[0 : l+len(data)] copy(slice[l:], data) *p = slice }
func (p *ByteSlice) Write(data []byte) (n int, err error) { slice := *p // Body as above, without the return. l := len(slice) if l+len(data) > cap(slice) { // reallocate // Allocate double what's needed, for future growth. newSlice := make([]byte, (l+len(data))*2) // The copy function is predeclared and works for any slice type. copy(newSlice, slice) slice = newSlice } slice = slice[0 : l+len(data)] copy(slice[l:], data) *p = slice *p = slice return len(data), nil }
func main() { var b ByteSlice b = b.Append([]byte{1, 2, 3}) fmt.Printf("byteSlice 1 is %v", b) b.Write([]byte{7, 8, 9}) fmt.Printf("byteSlice 2 is %v", b) /* func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) */ fmt.Fprintf(&b, "This hour has %d days\n", 7) /* if use below code , will throw error fmt.Fprintf(b, "This hour has %d days\n", 7) */ b.Append2([]byte{4, 5, 6}) fmt.Printf("byteSlice 3 is %v", b) }
as type io.Writer in argument to fmt.Fprintf: ByteSlice does not implement io.Writer (Write method has pointer receiver)
根据官方的描述,原文如下:
1 2 3
The rule about pointers vs. values for receivers is that value methods can be invoked on pointers and values, but pointer methods can only be invoked on pointers.
This rule arises because pointer methods can modify the receiver; invoking them on a value would cause the method to receive a copy of the value, so any modifications would be discarded. The language therefore disallows this mistake. There is a handy exception, though. When the value is addressable, the language takes care of the common case of invoking a pointer method on a value by inserting the address operator automatically. In our example, the variable b is addressable, so we can call its Write method with just b.Write. The compiler will rewrite that to (&b).Write for us.
For example, the documentation for bytes.Buffer states that "the zero value for Buffer is an empty buffer ready to use." Similarly, sync.Mutex does not have an explicit constructor or Init method. Instead, the zero value for a sync.Mutex is defined to be an unlocked mutex.
The zero-value-is-useful property works transitively. Consider this type declaration.
type SyncedBuffer struct { lock sync.Mutex buffer bytes.Buffer }
但是有些时候直接初始化0值不要足够,需要一个构建者。像这个例子一样
1 2 3 4 5 6 7 8 9 10 11
func NewFile(fd int, name string) *File { if fd < 0 { return nil } f := new(File) f.fd = fd f.name = name f.dirinfo = nil f.nepipe = 0 return f }
因为上面这段代码有比较多的参数,因此我们可以用一个命名的字段来继续初始化
1 2 3 4 5 6 7
func NewFile(fd int, name string) *File { if fd < 0 { return nil } f := File{fd, name, nil, 0} return &f }
func main(){ // allocates slice structure; *p == nil; rarely useful var p *[]int = new([]int) // the slice v now refers to a new array of 100 ints var v []int = make([]int, 5) fmt.Printf("p values is %v,%v\n", p, *p==nil) fmt.Printf("v values is %v, %v\n", v, v==nil) }
------------------ p values is &[],true v values is [0 0 0 0 0], false
// Methods required by sort.Interface. func (s Sequence) Len() int { return len(s) } func (s Sequence) Less(i, j int) bool { return s[i] < s[j] } func (s Sequence) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
// Copy returns a copy of the Sequence. func (s Sequence) Copy() Sequence { copy := make(Sequence, 0, len(s)) return append(copy, s...) }
// Method for printing - sorts the elements before printing. func (s Sequence) String() string { s = s.Copy() // Make a copy; don't overwrite argument. sort.Sort(s) str := "[" for i, elem := range s { // Loop is O(N²); will fix that in next example. if i > 0 { str += " " } str += fmt.Sprint(elem) } return str + "]" }
// 修改前 func (s Sequence) String() string { s = s.Copy() sort.Sort(s) return fmt.Sprint([]int(s)) }
// 修改后 type Sequence []int
// Method for printing - sorts the elements before printing func (s Sequence) String() string { s = s.Copy() sort.IntSlice(s).Sort() return fmt.Sprint([]int(s)) }
// PathError records an error and the operation and // file path that caused it. type PathError struct { Op string // "open", "unlink", etc. Path string // The associated file. Err error // Returned by the system call. }
func CubeRoot(x float64) float64 { z := x/3 // Arbitrary initial value for i := 0; i < 1e6; i++ { prevz := z z -= (z*z*z-x) / (3*z*z) if veryClose(z, prevz) { return z } } // A million iterations has not converged; something is wrong. panic(fmt.Sprintf("CubeRoot(%g) did not converge", x)) }
// Error is the type of a parse error; it satisfies the error interface. type Error string func (e Error) Error() string { return string(e) }
// error is a method of *Regexp that reports parsing errors by // panicking with an Error. func (regexp *Regexp) error(err string) { panic(Error(err)) }
// Compile returns a parsed representation of the regular expression. func Compile(str string) (regexp *Regexp, err error) { regexp = new(Regexp) // doParse will panic if there is a parse error. defer func() { if e := recover(); e != nil { regexp = nil // Clear return value. err = e.(Error) // Will re-panic if not a parse error. } }() return regexp.doParse(str), nil }
func Contents(filename string) (string, error) { f, err := os.Open(filename) if err != nil { return "", err } defer f.Close() // f.Close will run when we're finished.
var result []byte buf := make([]byte, 100) for { n, err := f.Read(buf[0:]) result = append(result, buf[0:n]...) // append is discussed later. if err != nil { if err == io.EOF { break } return "", err // f will be closed if we return here. } } return string(result), nil // f will be closed if we return here. }