目录
1、保留字段
2、预声明的常量、类型和函数
3、函数变参
4、defer延迟函数
4.1、修改函数返回值:
4.2、defer后进先出(LIFO):
5、map把函数作为value
6、defer、panic、recover
7、if
8、构建自定义包:
9、常用包:
10、自定义类型:
11、struct(method)
12、struct(匿名字段)
13、合法类型转换:
14、interface
15、interface、switch、reflect:
16、goroutine:
17、channel:
18、select:
19、获取url:
20、获取多个url:
21、简单的web服务器:
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
func main() {
a := [...]int{1,2,3}
test1(a[:]...)
}
func test1(arg ...int) {
for n := range arg {
fmt.Printf("And the number is: %d\n", n)
}
}
当前函数执行完之后,退出之前调用
func main() {
print(test1())
}
func test1() (result int) {
defer func() {
result++
}()
return 0
}
结果:
1
func main() {
for i := 0; i < 5; i++ {
defer fmt.Printf("%d ", i)
}
}
结果:
4 3 2 1 0
func main() {
var xs = map[int]func() int{
1: func() int { return 10 },
2: func() int { return 20 },
3: func() int { return 30 },
}
print(xs[1]())
}
结果:
10
如果当前的goroutine 产生了panic,这个defer 函数能够发现
func main() {
defer func() {
fmt.Println("c")
if err := recover(); err != nil {
fmt.Println(err)
}
fmt.Println("d")
}()
test1()
}
func test1() {
fmt.Println("a")
panic(55)
fmt.Println("b")
fmt.Println("f")
}
结果:
a
c
55
d
在if之后,条件语句之前,可以添加变量的初始化语句,使用;间隔
func main() {
a := 1
b := false
if b, a = true, 2; b == false && a == 2 {
}
}
这里注意,被调用的函数名首字母必须大写(小写为私有函数),不然调用不了
package test1
import "fmt"
func TestPrint() {
fmt.Println("test1")
}
然后放到GOPATH/Test1目录下
在cmd执行 go install test1,会在pkg目录下生成二进制文件
然后就可以直接调用了
package main
import "test1"
func main() {
test1.TestPrint()
}
fmt | 包fmt 实现了格式化的I/O 函数,这与C 的printf 和scanf 类似。格式化短语派生于C。一些短语(%-序列)这样使用: %v:默认格式的值。当打印结构时,加号(%+v)会增加字段名; %#v:Go 样式的值表达; %T:带有类型的Go 样式的值表达; |
io | 这个包提供了原始的I/O 操作界面。它主要的任务是对os 包这样的原始的I/O 进行封装,增加一些其他相关,使其具有抽象功能用在公共的接口上。 |
bufio | 这个包实现了缓冲的I/O。它封装于io.Reader 和io.Writer 对象,创建了另一个对象(Reader 和Writer)在提供缓冲的同时实现了一些文本I/O 的功能。 |
sort | sort 包提供了对数组和用户定义集合的原始的排序功能。 |
strconv | strconv 包提供了将字符串转换成基本数据类型,或者从基本数据类型转换为字符串的功能。 |
os | os 包提供了与平台无关的操作系统功能接口。其设计是Unix 形式的。 |
sync | sync 包提供了基本的同步原语,例如互斥锁。 |
flag | flag 包实现了命令行解析。 |
json | json 包实现了编码与解码RFC 4627 定义的JSON 对象。 |
template | 数据驱动的模板,用于生成文本输出,例如HTML。 将模板关联到某个数据结构上进行解析。模板内容指向数据结构的元素(通常结构的字段或者map 的键)控制解析并且决定某个值会被显示。模板扫描结构以便解析,而“游标”@ 决定了当前位置在结构中的值。 |
http | http 实现了HTTP 请求、响应和URL 的解析,并且提供了可扩展的HTTP 服务和基本的HTTP 客户端。 |
unsafe | unsafe 包包含了Go 程序中数据类型上所有不安全的操作。通常无须使用这个。 |
reflect | reflect 包实现了运行时反射,允许程序通过抽象类型操作对象。通常用于处理静态类型interface{} 的值,并且通过Typeof 解析出其动态类型信息,通常会返回一个有接口类型Type 的对象。包含一个指向类型的指针,*StructType、*IntType 等等,描述了底层类型的详细信息。可以用于类型转换或者类型赋值。 |
exec | exec 包执行外部命令。 |
func main() {
type foo int
var a foo
a = 1
print(a)
}
创建一个工作在这个类型上的函数,方法是作用在特定类型的变量上,因此自定义类型,都可以有方法,而不仅仅是struct
自定义类型和方法必须在同一个包
这里func (t *T) printT() 中使用指针 *T 是因为需要值传递
import "fmt"
type T struct {
Name string
Age int
}
func (t *T) printT() {
fmt.Println(t.Age, t.Name)
}
func main() {
t := T{}
fmt.Println(t)
t.Name = "back"
t.Age = 10
fmt.Println(t)
t.printT()
}
结果:
{ 0}
{back 10}
10 back
import "fmt"
type T struct {
string
int
}
func (t *T) printT() {
fmt.Println(t)
}
func main() {
t := T{"Jack", 12}
fmt.Println(t)
t.printT()
}
结果:
{Jack 12}
&{Jack 12}
import "fmt"
type S struct{ i int }
func (p *S) Get() int { return p.i }
func (p *S) Put(v int) { p.i = v }
type I interface {
Get() int
Put(int)
}
func main() {
var i I
i = new(S)
i.Put(2)
fmt.Println(i.Get())
}
结果:
2
只有公有变量才能反射
import (
"fmt"
"reflect"
)
type S struct{
Ii int "tag:int"
Jj bool "tag:bool"
}
func (p *S) Get() int { return p.Ii }
func (p *S) Put(v int) { p.Ii = v }
type R struct{ i int }
func (p *R) Get() int { return p.i }
func (p *R) Put(v int) { p.i = v }
type I interface {
Get() int
Put(int)
}
func f(p I) {
switch p.(type) {
case *S:
{
t := reflect.TypeOf(p)
v := reflect.ValueOf(p)
fmt.Println(v)
tag := t.Elem().Field(1).Tag
v.Elem().Field(1).SetBool(true)
name := v.Elem().Field(1).Bool()
fmt.Println(tag)
fmt.Println(name)
}
case *R:
default:
}
}
func main() {
var s S
f(&s)
}
结果:
&{0 false}
tag:bool
true
这里如果没有最后一句 time.Sleep(5 * 1e9),则两个goroutine中的内容都不会打印,这就需要channel了。
虽然goroutine 是并发执行的,但是它们并不是并行运行的。如果不告诉Go 额外的东西,同一时刻只会有一个goroutine 执行。利用runtime.GOMAXPROCS(n) 可以设置goroutine 并行执行的数量。
import (
"fmt"
"time"
)
func ready(w string, sec int64) {
time.Sleep(time.Duration(sec * 1e9))
fmt.Println(w, "is ready!")
}
func main() {
go ready("Tee", 2)
go ready("Coffee", 1)
fmt.Println("I'm waiting")
time.Sleep(5 * 1e9)
}
结果:
I'm waiting
Coffee is ready!
Tee is ready!
两个<-c,收到的值都被丢弃了,两次是因为有两个goroutine
import (
"fmt"
"time"
)
var c chan int
func ready(w string, sec int64) {
time.Sleep(time.Duration(sec * 1e9))
fmt.Println(w, "is ready!")
c <- 1
}
func main() {
c = make(chan int)
go ready("Tee", 2)
go ready("Coffee", 1)
fmt.Println("I'm waiting")
<-c
<-c
}
必须使用make 创建channel:
ci := make(chan int)
cs := make(chan string)
cf := make(chan interface{})
接收:
ci <- 1 ← 发送整数1 到channel ci
<-ci ← 从channel ci 接收整数
i := <-ci ← 从channel ci 接收整数,并保存到i 中
循环接收
import (
"fmt"
"time"
)
var c chan int
func ready(w string, sec int64) {
time.Sleep(time.Duration(sec * 1e9))
fmt.Println(w, "is ready!")
c <- 1
}
func main() {
c = make(chan int)
go ready("Tee", 2)
go ready("Coffee", 1)
fmt.Println("I'm waiting")
for i := 0; i < 2; i++ {
select {
case <-c:
}
}
}
import (
"fmt"
"io/ioutil"
"net/http"
"os"
)
func main() {
url := "http://www.kuaidi100.com/query?type=yuantong&postid=11111111111"
resp, err := http.Get(url)
if err != nil {
fmt.Fprintf(os.Stderr, "fetch: %v\n", err)
os.Exit(1)
}
b, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err!= nil {
fmt.Fprintf(os.Stderr, "fetch: reading %s: %v\n", url, err)
os.Exit(1)
}
fmt.Printf("%s", b)
}
import (
"fmt"
"io"
"io/ioutil"
"net/http"
"time"
)
func main() {
url := []string{
"http://www.kuaidi100.com/query?type=yuantong&postid=11111111111",
"http://www.kuaidi100.com/query?type=yuantong&postid=12345678901",
"http://baike.baidu.com/api/openapi/BaikeLemmaCardApi?scope=103&format=json&appid=379020&bk_key=%E9%95%BF%E6%B2%99&bk_length=600",
}
start := time.Now()
ch := make(chan string)
for _, urlT := range url{
go fetch(urlT, ch)
}
for range url[:] {
fmt.Println(<-ch)
}
fmt.Printf("%.2fs 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)
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.Sprintf("%.2fs %7d %s", secs, nbytes, url)
}
结果:
0.11s 11 http://baike.baidu.com/api/openapi/BaikeLemmaCardApi?scope=103&format=json&appid=379020&bk_key=%E9%95%BF%E6%B2%99&bk_length=600
0.17s 1301 http://www.kuaidi100.com/query?type=yuantong&postid=11111111111
0.17s 2189 http://www.kuaidi100.com/query?type=yuantong&postid=12345678901
0.17s elapsed
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe("localhost:8000", nil))
}
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path)
fmt.Printf("URL.Path = %q\n", r.URL.Path)
}