golang

今天开始看 the go programming language, 下面是一些比较奇怪的东西

变量

func two() (int, int) {
  return 1, 2
}

func main() {
  a, b := 1, 2 // a和b都是int
  a, b := two() // error
  ... // print

指针

package main

import "fmt"

type Point struct {
  x, y int
}

func (p Point) Init(x, y int) {
  p.x = x
  p.y = y
}

func (p *Point) Show() {
  fmt.Printf("{%d, %d}\n", p.x, p.y)
}

func main() {
  var p *Point = new(Point)
  p.Init(1, 2) // copy
  (*p).Init(1, 2) // copy p->Init() ????
  p.Show()
  (*p).Show() // p->Show() ????
}
/* print 
 {0, 0}
 {0, 0}
*/

作用域

var global *int

func _1s() *int {
  var x int = 233
  return &x
}

func _2s() {
  x := 233
  global = &x
}

func main() {
  var x *int = _1s()
  _2s()
  fmt.Println(*x, *global); // print 233 233

包和文件

var a = b + c // a 第三个初始化, 为 3
var b = f() // b 第二个初始化, 为 2, 通过调用 f (依赖c)
var c = 1 // c 第一个初始化, 为 1
func f() int { return c + 1 }

again

$ tree .
.
├── main.go
└── src
    └── echo
        └── echo.go

2 directories, 2 files
$ export GOPATH=/home/abby/go/pkg
$ go build main.go
$ ./main 233 233   
0 => 233
1 => 233  
$ cat main.go 
package main
// import ("os" "echo") // error
import (
  "os"
  "echo"
)

func main() {
  echo.Echo(os.Args[1:])
}
$ cat src/echo/echo.go 
package echo

import "fmt"

func Echo(args []string) {
  for k, v := range args {
    fmt.Printf("%d => %s\n", k, v)
  }
}

array 和 slice

package main

import "fmt"

func UpdateIntArray(a *[4]int, x int) {
  for idx, _ := range a {
    a[idx] = x
  }
}

func UpdateIntSlice(a []int, x int) {
  for idx, _ := range a {
    a[idx] = x
  }
}

func DisplayIntArray(a *[4]int) {
  fmt.Println("-------------------------------")
  for _, v := range a {
    fmt.Println(v)
  }
}

func DisplayIntSlice(a []int) {
  fmt.Println("-------------------------------")
  for _, v := range a {
    fmt.Println(v)
  }
}

func main() {
  a := [...]int {3: -1}
  z := [...]string {1: "one", 2: "two", 0: "zero"}
  s := z[0:2]
  fmt.Printf("%T\n%T\n%T\n", a, z, s)
  UpdateIntArray(&a, 1)
  DisplayIntArray(&a)
  UpdateIntSlice(a[1:], 2)
  DisplayIntSlice(a[:])
  la := [...]int {1, 2, 3, 4, 5, 6}
  //UpdateIntArray(&la, 233) // error
  //DisplayIntArray(&la) // error
  UpdateIntSlice(la[:], 233)
  DisplayIntSlice(la[:])
}

打印出

[4]int
[3]string
[]string
-------------------------------
1
1
1
1
-------------------------------
1
2
2
2
-------------------------------
233
233
233
233
233
233

结构体

… 非常原始

函数

匿名函数

func main() {
  func (x int, f func(int) int) {
    fmt.Println(f(x))
  }(233, func(x int) int {
    return x * x
  })
}
// print 54289

可变参数
非常原始, 可看做 同一类型的slice

Deferred
伪RAII

func main() {
  defer func() {
    fmt.Println("close file")
  }()

  fmt.Println("open file and read something")
}

/* print
open file and read something
close file
*/

异常与异常恢复

Golang不推荐使用panic,要优雅,不要崩溃. 恢复需要defer辅助

func damn(x string) {
  panic(x)
}

func main() {
  defer func() {
    if r := recover(); r != nil {
      fmt.Printf("recover from panic: %s\n", r)
    }
  }()
  damn("yuck!")
  fmt.Println("something else") // never display
}

// print: recover from panic: yuck!

OOP (伪)

Golang所谓的OOP指的是: 封装, 组合.

type Node struct {
  data int
  next *Node
}

func New(x int, next *Node) *Node {
  n := new(Node)
  n.data = x
  n.next = next
  return n
}

type List struct {
  head *Node
}

func (l *List) Init() {
  l.head = New(0, nil)
}

func (l *List) Insert(x int) {
  l.head.next = New(x, l.head.next)
}

func (l *List) Show() {
  for n := l.head.next; n != nil; n = n.next {
    fmt.Printf("%d ", n.data)
  }
  fmt.Println()
}

func (l *Node) Disp() {
  if l.next != nil {
    fmt.Printf("%d ", l.next.data)
    l.next.Disp()
  } else {
    fmt.Println()
  }
}

type Base struct {
  x int
}

func (x Base) showBase() {
  fmt.Printf("Base: {x : %d}\n", x.x)
}

type FakeDrive struct {
  Base
}

func (x FakeDrive) showFakeDrive() {
  fmt.Printf("Drive: {x : %d}\n", x.x)
}


func main() {
  l := List{nil}
  l.Init()

  for i := 0; i < 10; i++ {
    l.Insert(i)
  }

  l.Show()
  l.head.Disp()

  var d FakeDrive = FakeDrive{Base{233}}
  d.showBase()
  d.showFakeDrive()
  // var pd *Base = &d // error
}

示例:Bit数组

type Set struct {
  data []uint64
}

func (s *Set) Add(x int) {
  w, b := x/64, uint(x%64)
  for w >= len(s.data) {
    s.data = append(s.data, 0)
  }
  s.data[w] |= (1 << b)
}

func (s *Set) AddAll(x ...int) {
  for _, m := range x {
    s.Add(m)
  }
}

func (s *Set) Has(x int) bool {
  w, b := x/64, uint(x%64)
  return w < len(s.data) && (s.data[w] & (1 << b)) != 0
}

func (s *Set) UnionWith(t *Set) {
  for i, w := range t.data {
    if i < len(t.data) {
      s.data[i] |= w
    } else {
      s.data = append(s.data, w)
    }
  }
}

func (s *Set) IntersectWith(t *Set) {
  for i, w := range s.data {
    if w == 0 {
      continue
    }
    for _, b := range t.data {
      if b == 0 {
        continue
      }
      for k := 0; k < 64; k++ {
        bit := uint64(1 << uint(k))
        if w & bit != 0 && b & bit == 0 {
          s.Remove(i * 64 + k)
        }
      }
    }
  }
}

func (s *Set) DifferenceWith(t *Set) {
  for i, w := range s.data {
    if w == 0 {
      continue
    }

    for _, b := range t.data {
      if b == 0 {
        continue
      }
      for k := 0; k < 64; k++ {
        bit := uint64(1 << uint(k))
        if w & bit != 0 && b & bit != 0 {
          s.Remove(i * 64 + k)
        }
      }
    }
  }
}

func (s *Set) SymmetricDifference(t *Set) {
  for i, w := range s.data {
    if w == 0 {
      continue
    }
    for _, b := range t.data {
      if b == 0 {
        continue
      }
      for k := 0; k < 74; k++ {
        bit := uint64(1 << uint(k))
        if w & bit != 0 && b & bit != 0 {
          s.Remove(i * 64 + k)
        } else if w & bit == 0 && b & bit != 0 {
          s.Add(i * 64 + k)
        }
      }
    }
  }
}

func (s *Set) Len() int {
  var len int
  for _, v := range s.data {
    if v != 0 {
      len++
    }
  }
  return len
}

func (s *Set) Remove(x int) {
  w, m := x/64, uint(x%64)
  if w < len(s.data) {
    if s.data[w] != 0 && s.data[w] & (1 << m) != 0 {
      s.data[w] &= ^(1 << m)
    }
  }
}

func (s *Set) Clear() {
  for i, _ := range s.data {
    s.data[i] = 0
  }
}

func (s *Set) Copy() *Set {
  var res *Set = new(Set)
  for _, b := range s.data {
    res.data = append(res.data, b)
  }
  return res
}

func (l *Set) Equal(r *Set) bool {
  if len(l.data) != len(r.data) {
    return false
  }
  for k, _ := range l.data {
    if l.data[k] != r.data[k] {
      return false
    }
  }
  return true
}

func (s *Set) String() string {
  var buf bytes.Buffer
  buf.WriteByte('{')
  for i, w := range s.data {
    if w == 0 {
      continue
    }

    for j := 0; j < 64; j++ {
      if w & (1 << uint(j)) != 0 {
        if buf.Len() > len("{") {
          buf.WriteByte(' ')
        }
        fmt.Fprintf(&buf, "%d", 64 * i + j)
      }
    }
  }
  buf.WriteByte('}')
  return buf.String()
}

// 上面是前5章和第6章(方法)的部分,今天就看了这么多点, 明天继续…