目录

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服务器:


 

 

1、保留字段

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

2、预声明的常量、类型和函数

golang func 传递类型 golang define_字段

3、函数变参

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)
	}
}

4、defer延迟函数

当前函数执行完之后,退出之前调用

4.1、修改函数返回值:

func main() {
	print(test1())
}

func test1() (result int) {
	defer func() {
		result++
	}()
	return 0
}

结果:
1

4.2、defer后进先出(LIFO):

func main() {
	for i := 0; i < 5; i++ {
		defer fmt.Printf("%d ", i)
	}
}

结果:
4 3 2 1 0

5、map把函数作为value

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

6、defer、panic、recover

如果当前的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

7、if

在if之后,条件语句之前,可以添加变量的初始化语句,使用;间隔

func main() {
	a := 1
	b := false
	if b, a = true, 2; b == false && a == 2 {

	}
}

8、构建自定义包:

这里注意,被调用的函数名首字母必须大写(小写为私有函数),不然调用不了

package test1

import "fmt"

func TestPrint() {
	fmt.Println("test1")
}

然后放到GOPATH/Test1目录下

在cmd执行  go install test1,会在pkg目录下生成二进制文件

然后就可以直接调用了

package main

import "test1"

func main() {
	test1.TestPrint()
}

9、常用包:

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 包执行外部命令。

10、自定义类型:

func main() {
	type foo int
	var a foo
	a = 1
	print(a)
}

11、struct(method)

创建一个工作在这个类型上的函数,方法是作用在特定类型的变量上,因此自定义类型,都可以有方法,而不仅仅是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

12、struct(匿名字段)

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}

13、合法类型转换:

golang func 传递类型 golang define_go_02

14、interface

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

15、interface、switch、reflect:

只有公有变量才能反射

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

16、goroutine:

这里如果没有最后一句 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!

17、channel:

两个<-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 中

18、select:

循环接收

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:
		}
	}
}

19、获取url:

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)
}

20、获取多个url:

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

21、简单的web服务器:
 

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)
}

golang func 传递类型 golang define_golang func 传递类型_03