Go intro

 “package declaration”. Every Go program must start with a package declaration. Packages are Go's way of organizing and reusing code. There are two types of Go programs: executables and libraries.

import "fmt"
The import keyword is how we include code from other packages to use with our program. The fmt package (shorthand for format) implements formatting for input and output.

All functions start with the keyword  func followed by the name of the function ( main  in this case), a list of zero or more “parameters” surrounded by parentheses, an optional return type and a “body” which is surrounded by curly braces.   整个签名式的顺序类似于C++ lambda。

The Println function does the real work in this program. You can find out more about it by typing the following in your terminal:

godoc fmt Println

Go's integer types are:  uint8 uint16 uint32 uint64 int8 int16 int32  and  int64.
byte  which is the same as  uint8  and  rune  which is the same as  int32 .
Go's  byte  data type is often used in the definition of other types. There are also 3 machine dependent integer types:  uint int  and  uintptr . They are machine dependent because their size depends on the type of architecture you are using.

float32  and  float64,   complex numbers (numbers with imaginary parts):  complex64  and  complex128 . Generally we should stick with  float64  when working with floating point numbers.

String literals can be created using double quotes  "Hello World"  or back ticks  `Hello World` .  后者允许字符串里面出现多行,类似于python的"""。
str[idx]输出字符对应的int值;Go的字符串没有末尾的'\0'.


var/const x string = "Hello World"
x := "Max"
var x = "Hello World"

var (
  x = 5
  y = 6
) 定义多个变量
第一种是最标准的写法;后两者是因为Go compiler”见多识广“可以识别这种情况。

全局变量在使用时候不需要加global;可以调用同一个文件中的函数,不需要声明。



Go build&install  入门, https://studygolang.com/articles/2233
Go编译和install时候要求package文件必须位于GOPATH环境变量的路径下面,可以使用go env查看相关的环境变量。
go install会在/src, /pkg, /bin的/pkg/os_arch/目录下面编译出一个.a library文件,其中os_arch=linux_amd64

Best practice: 所有的source file写在/src下面,并且文件夹,文件,package具有相同的名字,当然同一个文件夹下面可以包含多个.go文件。


go test
如果报错cannot use matchString ... as type testing.testDeps,可能是因为系统里安装了多个go版本,出现版本冲突。
which go看版本,把旧版本删除,然后ln -s GO_PATH /usr/bin/go可以解决问题



select可以接受事件或者channel
x := 0
tick := time.Tick(100 * time.Millisecond)
c := make(chan int)
select {
     case <- tick:
          fmt.Println("tick.")
     case c <- x:
          fmt.Println(<-c)
}



Go's basic types are
bool
string
int  int8  int16  int32  int64
uint uint8 uint16 uint32 uint64 uintptr
byte // alias for uint8
rune // alias for int32
     // represents a Unicode code point
float32 float64
complex64 complex128
fmt.Printf("%T %v %q")分别输出type, value, raw data.




其中,method可以写在不同的文件,但是必须与Class在同一个类中。【package使用Method/method表示exposure,但是class method不行。
func (obj Class) Method(para lit) returnType {
}


func (v *Vertex) Scale(f float64){}这里的pointer receiver表示可以更改属性值。但依然使用v.X访问属性,调用方式也是v.Scale()。但是如果Scale写为函数,必须使用&v传递参数给*Vertex,访问属性方法不变。
The first is so that the method can modify the value that its receiver points to.
The second is to avoid copying the value on each method call. 
In general, all methods on a given type should have either value or pointer receivers, but not a mixture of both. 
A type implements an interface by implementing its methods.  并不能显式声明implement某个interface。
目前能看到的interface的用法就是声明一个I类型的变量i,赋值为T类型,调用interface声明过的方法。
var i I = T{"hello"}
i.M()


目前没有看到interface接受过receiver参数。
假设
type I interface {
  M()
}
func (t T) M() {  
  fmt.Println(t.S)
}
// 如果interface method接受T类型参数,传一个指针,可以接受;但是如果接受*T,不能使用T类型的obj调用这个method,因为interface类型。
i := T{"hello"}
i.M()
如果是普通class method,可以*T调用receiver T类型的method;可以T调用receiver *T的method。
但是如果interface method,不能使用T调用receiver *T的method,认为T does not implement I(M method has pointer receiver).
四种情况
*T调用receiver *T,应该是把*T当作一种类型
T调用receiver T,正常。
*T调用receiver T,不知道为啥。。
T调用receiver *T,失败;




type T struct {
  S string
  T int
  B string
}
i = &T{"Hello", 2, "nihao"}
自定义类型初始化 i = T{para list},好像必须按声明顺序传值。此时i value= &{Hello 2 nihao}, type=*main.T
built-in类型 i = float64(2.3)
新定义一个指针的方式是i := &T{},即先创建一个obj然后取地址。
var t *T 此时t是指向nil的*T类型指针;
var t T 此时t是一个空object.
var i interface{}这样的话,i可以被赋值为任何类型【因为空interface对type没任何要求】,但是不能调用任何方法;




https://tour.golang.org/methods/15 type assertion
A type assertion provides access to an interface value's underlying concrete value.
t := i.(T)
This statement asserts that the interface value i holds the concrete type T and assigns the underlying T value to the variable t.
If i does not hold a T, the statement will trigger a panic.
To test whether an interface value holds a specific type, a type assertion can return two values: the underlying value and a boolean value that reports whether the assertion succeeded.
t, ok := i.(T)
If i holds a T, then t will be the underlying value and ok will be true.
If not, ok will be false and t will be the zero value of type T, and no panic occurs.
比如,
var i interface{} = "hello"


s := i.(string)
fmt.Println(s)


s, ok := i.(string)
fmt.Println(s, ok) // hello true


f, ok := i.(float64)
fmt.Println(f, ok) // 0 false


f = i.(float64) // panic
fmt.Println(f)
https://tour.golang.org/methods/16 type switch
A type switch is a construct that permits several type assertions in series.
A type switch is like a regular switch statement, but the cases in a type switch specify types (not values), and those values are compared against the type of the value held by the given interface value.
switch v := i.(type) { // 这里使用i.(type)而不是上面的i.(string)
case T:
    // here v has type T 这里v是类型T
case S:
    // here v has type S
default:
    // no match; here v has the same type as i
}


byte->string: ret += strconv.Itoa(int(no))


fmt.Stringer是一个interface,定义了String()string{}接口;如果一个类重写了这个接口,在%v格式输出时候会输出返回值;
type T如果有func (t T)String() string {},在输出时候会自动调用,但receiver必须是T而不是*T。
同理,type error interface{ Error() string}接口
type MyError struct {
  When time.Time
  What string
}


func (e *MyError) Error() string {  // Error interface
  return fmt.Sprintf("at %v, %s",  // fmt.Sprintf和C类似
    e.When, e.What)
}


func run() error {  // 注意这里返回的是error,built-in class,返回值实际是*MyError类型的值。如果把return 和 Error()的receiver同时改为MyError类型,可以work
  return &MyError{ // 返回一个
    time.Now(),
    "it didn't work",
  }
}


func main() {
  if err := run(); err != nil {
    fmt.Println(err)
  }
}












b := make([]byte, 8)
n, err := r.Read(b) // func (T) Read(b []byte) (n int, err error)
这里函数Read作为类成员函数,从T读bytes存入参数b,返回读的bytes数,和error msg(如果EOF,返回io.EOF)








c := make(chan int)
go sum(s[:len(s)/2], c)
go sum(s[len(s)/2:], c)
x, y := <-c, <-c // receive from c
channel是typed;这里的代码是向c发送两次,接收两次。


package main


import (
  "fmt"
  "time"
)


func buf(ch chan int) {
  fmt.Println("start buffer")
  ch <- 2
  fmt.Println("end buffer")
}


func main() {
  ch := make(chan int, 1)
  ch <- 1
  go buf(ch)
  time.Sleep(100 * time.Millisecond)
  fmt.Println(<-ch)
  fmt.Println(<-ch)
  fmt.Println("Main End")
}
goroutine如果main执行完退出,可能有些子goroutine的语句不执行,直接整个程序退出?
https://gobyexample.com/closing-channels
channel如果想标识end,
close(CHANNEL)和  val, ok := <- CHANNEL; if ok 搭配使用。




Go struct
https://golang.org/ref/spec#Struct_types

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值