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章(方法)的部分,今天就看了这么多点, 明天继续…