hello hacker

第一个go代码

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. fmt.Println("hello blackhat-go")
  7. }
  1. go build -ldflags "-w -s" main.go # 减小编译文件大小

image.png

windows交叉编译

image.png

基本语法

变量声名

  1. var x = "Hello World"
  2. z := int(42) //隐式推导类型

切片(slice)和hash表(map)

  1. var s = make([]string, 0)//声名一个string类型切片
  2. var m = make(map[string]string)//声名一个key,value都为string的map
  3. s = append(s, "some string") // append添加元素
  4. m["some key"] = "some value" // 直接赋值

指针

  1. var count = int(42)
  2. ptr := &count
  3. fmt.Println(*ptr)
  4. *ptr = 100
  5. fmt.Println(count)

学习过C的,应该对指针不陌生
image.png

结构体

  1. type Person struct {
  2. Name string
  3. Age int
  4. }
  5. func (p *Person) SayHello() {
  6. fmt.Println("Hello,", p.Name)
  7. }
  8. func main() {
  9. var guy = new(Person)
  10. guy.Name = "Dave"
  11. guy.SayHello()
  12. }

image.png
这里值得注意的是go语言变量使用大小写首字母来标注成员是否可导出,也就是是否外部可访问,如果首字母大写。则外部可访问,否则不可访问。

接口(interface)

  1. type Friend interface {
  2. SayHello()
  3. }

friend接口声名了一个方法SayHello(),如果实现了SayHello方法,那么他就是一个Friend。如

  1. type Dog struct {}
  2. func (d *Dog) SayHello(){
  3. fmt.Println("Woof woof")
  4. }
  1. func Greet (f Friend) {
  2. f.SayHello()
  3. }

这里Greet方法要求传入一个Friend,并且会调用SayHello函数。在之前的Person结构体实现了SayHello函数,Dog也实现了SayHello,那么两者都可以传入Greet方法。执行结果

  1. package main
  2. import "fmt"
  3. type Person struct {
  4. Name string
  5. Age int
  6. }
  7. func (p *Person) SayHello() {
  8. fmt.Println("Hello,", p.Name)
  9. }
  10. type Friend interface{
  11. SayHello()
  12. }
  13. type Dog struct {}
  14. func (d *Dog) SayHello(){
  15. fmt.Println("Woof woof")
  16. }
  17. func Greet (f Friend) {
  18. f.SayHello()
  19. }
  20. func main() {
  21. var guy = new(Person)
  22. guy.Name = "Dave"
  23. Greet(guy)
  24. var dog = new(Dog)
  25. Greet(dog)
  26. }

image.png
怎么说呢,有点像多态。。

控制流程

没啥好说的

  1. if x == 1 {
  2. fmt.Println("X is equal to 1")
  3. } else {
  4. fmt.Println("X is not equal to 1")
  5. }

这里的条件不需用括号包裹,但控制体必须要用大括号包裹。

  1. switch x {
  2. case "foo":
  3. fmt.Println("Found foo")
  4. case "bar":
  5. fmt.Println("Found bar")
  6. default:
  7. fmt.Println("Default case")
  8. }

for循环

  1. for i := 0; i < 10; i++ {
  2. fmt.Println(i)
  3. }

另外一种形式

  1. nums := []int{2,4,6,8}
  2. for idx, val := range nums {
  3. fmt.Println(idx, val)
  4. }

这里的idx和val分别为切片的index和值,需要注意的是原文为copy of the current value`` at that index,说明它只是一个拷贝,对其修改不会修改原值。

并发

  1. func f() {
  2. fmt.Println("f function")
  3. time.Sleep(2 * time.Second)
  4. fmt.Println("f complete")
  5. }
  6. func main() {
  7. go f()
  8. fmt.Println("main function")
  9. time.Sleep(3 * time.Second)
  10. }

image.png

chan

  1. unc strlen(s string, c chan int) {
  2. c <- len(s)
  3. }
  4. func main() {
  5. c := make(chan int)
  6. go strlen("hello hacker",c)
  7. go strlen("hacker",c)
  8. x,y:=<-c,<-c // 这里进行阻塞直到能够拿到数据再解除阻塞。
  9. fmt.Println(x,y,x+y)
  10. }

image.png

错误处理

  1. func foo() error {
  2. return errors.New("Some Error Occurred")
  3. }
  4. func main() {
  5. if err := foo();err != nil {
  6. fmt.Println(err)
  7. }else {
  8. fmt.Println("success")
  9. }
  10. }

JSON&XML

  1. type Foo struct {
  2. Bar string
  3. Baz string
  4. }
  5. func main() {
  6. f := Foo{"Joe Junior", "Hello Shabado"}
  7. b, _:= json.Marshal(f)
  8. fmt.Println(string(b))
  9. json.Unmarshal(b, &f)
  10. fmt.Println(f.Bar)
  11. }

image.png

  1. type Foo struct {
  2. Bar string `xml:"id,attr"`
  3. Baz string `xml:"parent>child"`
  4. }
  5. func main() {
  6. f := Foo{"Joe Junior", "Hello Shabado"}
  7. b, _:= xml.Marshal(f)
  8. fmt.Println(string(b))
  9. xml.Unmarshal(b, &f)
  10. fmt.Println(f.Bar)
  11. }

image.png