Go程序设计语言读书笔记
- 第一章-入门
Go代码使用包来组织的,包类似其他语言中的库和模块,一个包由一个或者多个.go源文件组成,放在同一个文件夹中,文件夹的名字描述了包的作用。每一个源文件的开始都用package声明,列子里面是package main,说明这个文件属于哪一个包。
main是一个用来定义一个独立的可执行程序。
import声明必须跟在package后面。import导入声明后,是组成程序的函数、变量、常量、类型声明。
Go语言不需要再语句或声明后面使用分号结尾,除非有多个语句或声明出现在同一行。
for是Go里面的唯一循环语句,有几种形式。其中一种:
`for initialization;condition;post{
// 零个或多个语句
}`
map存储一个键/值对集合。内置函数make可以用来新建map。
map是一个使用make创建的数据结构的引用。当一个map被传递给一个函数时,函数接收到这个引用的副本,所以被调用函数中对于map数据结构中的改变对函数调用者使用的map引用也是可见的。
func main(){
counts := make(map[string]int)
files := os.Args[1:]
if len(files) == 0{
countLines(os.Stdin,counts)
}else{
for _,arg := range files{
f,err := os.Open(arg)
if err != nil{
fmt.Fprint(os.Stderr,"dup2:%v\n",err)
continue
}
countLines(f,counts)
f.Close()
}
}
for line,n := range counts{
if n>1{
fmt.Print("%d]t%s\n",n,line)
}
}
}
func countLines(f *os.File,counts map[string]int){
input := bufio.NewScanner(f)
for input.Scan(){
if input.Text() == "end"{
break;
}
counts[input.Text()]++
}
}
bufio包,使用它可以简便和高效地处理输入和输出。扫描器(Scanner)的类型,它可以读取输入,以行或者单词为单位断开。如下:新建一个bufio.Scanner类型input变量;
input :=bufio.NewScanner(os.Stdin)
从程序的标准输入进行读取。调用input.Scan()读取下一行,并且将结尾的换行符去掉;通过调用input.Text()来获取读到的内容。Scan函数在读到新行返回True,没有更多内容返回false。
const 声明用来给常量命名,常量是在编译期间固定的量。
func main(){ hljs 30行
start := time.Now()
ch :=make(chan string)
for _,url := range os.Args[1:]{
go fetch(url,ch) //启动一个线程
}
for range os.Args[1:]{
fmt.Println(<-ch) //从通道ch接受
}
fmt.Println("%.2f elapsed\n",time.Since(start).Seconds())
}
func fetch(url string,ch chan<- string){
start := time.Now()
resp,err := http.Get(url)
if err != nil{
ch <- fmt.Sprint(err) //发送到通道ch
return
}
nbytes ,err := io.Copy(ioutil.Discard,resp.Body)
resp.Body.Close() //不要泄露资源
if err != nil{
ch <- fmt.Sprintf("while reading %s: %v",url,err)
return
}
secs := time.Since(start).Seconds()
ch <- fmt.Sprint("%.2fs %7d %s",secs,nbytes,url)
}
goroutine是一个并发执行执行的函数。通道是一种运行某一例程向另一个例程传递指定类型的值的通信机制。main函数在一个goroutine中执行,然后go语句创建额外的goroutine。
当一个goroutine试图在一个通道上进行发送或接受操作时,他会阻塞,直到另一个goroutine试图进行接受或者发送操作才传递值,并开始处理两个goroutine。
Go提供了指针,他的值是变量的地址