Go by Example练习

代码如下:

package main

import "fmt"

func f(from string){
	for i:=0;i<3;i++{
		fmt.Println(from,":",i)
	}
}

func main(){
	f("direct")

	go f("goroutine")

	go func(msg string){
		fmt.Println(msg)
	}("going")

	var input string
	fmt.Scanln(&input)
	fmt.Println("done")
}

结果如下:

direct : 0
direct : 1
direct : 2
goroutine : 0
going
goroutine : 1
goroutine : 2


done

 

代码如下:

package main

import "fmt"

func main(){
	messages := make(chan string)
	
	go func(){
		messages <- "ping"
	}()
    
    //也可以用通道缓冲
    //messages := make(chan string, 1)
    //messages <- "ping"
	
	msg := <-messages
	fmt.Println(msg)
}

结果如下:

ping

 

代码如下:

package main

import (
	"fmt"
)

func main(){
	messages := make(chan string,2)

	messages <- "buffered"
	messages <- "channel"

	fmt.Println(<-messages)
	fmt.Println(<-messages)
}

结果如下:

buffered
channel

 

代码如下:

package main

import (
	"fmt"
	"time"
)

func worker(done chan bool){
	fmt.Println("working...")
	time.Sleep(time.Second)
	fmt.Println("done")

	done <- true
}

func main(){
	done := make(chan bool)
	go worker(done)

	//也可以用通道缓冲
	//done := make(chan bool, 1)
	//worker(done)
	<-done
}

结果如下:

working...
done

 

代码如下:

package main

import (
	"fmt"
	"time"
)

func main(){
	ch1 := make(chan string)
	ch2 := make(chan string)

	go func(){
		time.Sleep(time.Second)
		ch1 <- "one"
	}()

	go func(){
		time.Sleep(time.Second*2)
		ch2 <- "two"
	}()

	for i:=0;i<2;i++{
		select {
		case msg1 := <- ch1:
			fmt.Println("received",msg1)
		case msg2 := <- ch2:
			fmt.Println("received",msg2)
		}
	}
}

结果如下:

received one
received two

 

代码如下:

package main

import (
	"fmt"
	"time"
)

func main(){
	c1 := make(chan string)
	go func(){
		time.Sleep(time.Second*2)
		c1 <- "result1"
	}()
	select {
	case res := <- c1:
		fmt.Println(res)
	case <- time.After(time.Second):
		fmt.Println("timeout1")
	}

	c2 := make(chan string)
	go func(){
		time.Sleep(time.Second)
		c2 <- "result2"
	}()
	select {
	case res := <- c2:
		fmt.Println(res)
	case <- time.After(time.Second*2):
		fmt.Println("timeout2")
	}
}

结果如下:

timeout1
result2

 

代码如下:

package main

import "fmt"

func main(){
	messages := make(chan string)//若有通道缓冲,则能够收到
	signals := make(chan string)

	select {
	case msg := <- messages:
		fmt.Println("received message",msg)
	default:
		fmt.Println("no messages received")
	}

	msg := "hi"
	select {
	case messages <- msg:
		fmt.Println("sent message",msg)
	default:
		fmt.Println("no messages sent")
	}

	select {
	case msg := <- messages:
		fmt.Println("received message",msg)
	case sig := <- signals:
		fmt.Println("received signal",sig)
	default:
		fmt.Println("no activity")
	}
}

结果如下:

no messages received
no messages sent
no activity

 

代码如下:

package main

import "fmt"

func main(){
	jobs := make(chan int, 5)
	done := make(chan bool)

	go func(){
		for{
			value, more := <- jobs
			if more{
				fmt.Println("received job",value)
			}else{
				fmt.Println("received all jobs")
				done <- true
				return
			}
		}
	}()

	for i:=1;i<=3;i++{
		jobs <- i
		fmt.Println("sent job",i)
	}
	close(jobs)
	fmt.Println("sent all jobs")

	<-done
}

结果如下:

sent job 1
received job 1
received job 2
sent job 2
sent job 3
sent all jobs
received job 3
received all jobs

 

代码如下:

package main

import "fmt"

func main(){
	queue := make(chan string, 2)
	queue <- "one"
	queue <- "two"
	close(queue)

	for elem := range queue{
		fmt.Println(elem)
	}
}

结果如下:

one
two

 

代码如下:

package main

import (
	"fmt"
	"time"
)

func main(){
	timer1 := time.NewTimer(time.Second)

	<-timer1.C
	fmt.Println("Timer1 expired")

	timer2 := time.NewTimer(time.Second)
	go func(){
		<-timer2.C
		fmt.Println("Timer2 expired")
	}()
	timer2.Stop()
	fmt.Println("Timer2 stopped")
}

结果如下:

Timer1 expired
Timer2 stopped

 

代码如下:

package main

import (
	"fmt"
	"time"
)

func main(){
	ticker := time.NewTicker(time.Millisecond*500)
	go func(){
		for i := range ticker.C{
			fmt.Println("Tick at",i)
		}
	}()

	time.Sleep(time.Millisecond*1600)
	ticker.Stop()
	fmt.Println("Ticker stopped")
}

结果如下:

Tick at 2018-11-22 11:11:08.8536293 +0800 CST m=+0.506127601
Tick at 2018-11-22 11:11:09.3536449 +0800 CST m=+1.006143201
Tick at 2018-11-22 11:11:09.8539063 +0800 CST m=+1.506404601
Ticker stopped

 

代码如下:

package main

import (
	"fmt"
	"time"
)

func worker(id int, jobs <-chan int, results chan<- int){
	for i := range jobs{
		fmt.Println("worker",id,"processing job",i)
		time.Sleep(time.Second)
		results <- i*2
	}
}

func main() {
	jobs := make(chan int, 100)
	results := make(chan int, 100)

	for m:=1;m<=3;m++{
		go worker(m,jobs,results)
	}

	for i:=1;i<=9;i++{
		jobs <- i
	}
	close(jobs)

	for j:=1;j<=9;j++{
	<- results
	}
}

结果如下:

worker 2 processing job 2
worker 1 processing job 1
worker 3 processing job 3
worker 1 processing job 4
worker 2 processing job 5
worker 3 processing job 6
worker 2 processing job 7
worker 1 processing job 8
worker 3 processing job 9

 

代码如下:

package main

import (
	"fmt"
	"time"
)

func main() {
	requests := make(chan int,5)
	for i:=1;i<=5;i++{
		requests <- i
	}
	close(requests)

	limiter := time.Tick(time.Millisecond*200)
	for req := range requests{
		<-limiter
		fmt.Println("request",req,time.Now())
	}

	burstyLimiter := make(chan time.Time,3)
	for i:=1;i<=3;i++{
		burstyLimiter <- time.Now()
	}

	go func() {
		t := time.Tick(time.Millisecond*200)
		for i := range t{
			burstyLimiter <- i
		}
	}()

	burstyRequests := make(chan int,5)
	for j:=1;j<=5;j++{
		burstyRequests <- j
	}
	close(burstyRequests)

	for req := range burstyRequests{
		<- burstyLimiter//tn := <- burstyLimiter
		fmt.Println("request",req,time.Now())//fmt.Println("request",req,tn)
	}
}

结果如下:

request 1 2018-11-22 13:31:12.5932522 +0800 CST m=+0.208619801
request 2 2018-11-22 13:31:12.793778 +0800 CST m=+0.409145601
request 3 2018-11-22 13:31:12.9931922 +0800 CST m=+0.608559801
request 4 2018-11-22 13:31:13.1937051 +0800 CST m=+0.809072801
request 5 2018-11-22 13:31:13.393264 +0800 CST m=+1.008631601
request 1 2018-11-22 13:31:13.393264 +0800 CST m=+1.008631601
request 2 2018-11-22 13:31:13.393264 +0800 CST m=+1.008631601
request 3 2018-11-22 13:31:13.393264 +0800 CST m=+1.008631601
request 4 2018-11-22 13:31:13.5933922 +0800 CST m=+1.208759901
request 5 2018-11-22 13:31:13.7938431 +0800 CST m=+1.409210701

 

package main

import (
	"fmt"
	"runtime"
	"sync/atomic"
	"time"
)

func main() {
	var ops uint64 = 0

	for i:=0;i<50;i++{
		go func() {
			for{
				atomic.AddUint64(&ops,1)
				runtime.Gosched()//让出CPU时间片
			}
		}()
	}

	time.Sleep(time.Second)
	opsFinal := atomic.LoadUint64(&ops)
	fmt.Println("ops:",opsFinal)
}

结果如下:

ops: 3139216

 

代码如下:

package main

import (
	"fmt"
	"math/rand"
	"runtime"
	"sync"
	"sync/atomic"
	"time"
)

func main() {
	var state = make(map[int]int)
	var mutex = &sync.Mutex{}
	var ops uint64 = 0

	for m:=0;m<10;m++{
		go func() {
			for{
				key := rand.Intn(5)
				val := rand.Intn(100)
				mutex.Lock()
				state[key]=val
				mutex.Unlock()
				atomic.AddUint64(&ops,1)

				runtime.Gosched()
			}
		}()
	}
	time.Sleep(time.Second)

	opsFinal := atomic.LoadUint64(&ops)
	fmt.Println("ops:",opsFinal)

	mutex.Lock()
	fmt.Println(state)
	mutex.Unlock()
}

结果如下:

ops: 2072334
map[1:65 0:85 2:25 4:65 3:54]

 

代码如下:

package main

import (
	"fmt"
	"math/rand"
	"sync/atomic"
	"time"
)

type readOp struct {
	key  int
	resp chan int
}
type writeOp struct {
	key  int
	val  int
	resp chan bool
}

func main() {
	var ops uint64

	reads := make(chan *readOp)
	writes := make(chan *writeOp)

	go func() {
		var state = make(map[int]int)
		for{
			select {
			case read := <- reads:
				read.resp <- state[read.key]
			case write := <- writes:
				state[write.key] = write.val
				write.resp <- true
			}
		}
	}()

	for r:=0;r<100;r++{
		go func() {
			for {
				read := &readOp{
					rand.Intn(5),
					make(chan int)}
				reads <- read
				<-read.resp
				atomic.AddUint64(&ops, 1)
			}
			//runtime.Gosched()
		}()
	}

	for w:=0;w<10;w++{
		go func() {
			for{
				write := &writeOp{
					rand.Intn(5),
					rand.Intn(100),
					make(chan bool)}
				writes <- write
				<- write.resp
				atomic.AddUint64(&ops,1)
			}
			//runtime.Gosched()
		}()
	}

	time.Sleep(time.Second)

	opsFinal := atomic.LoadUint64(&ops)
	fmt.Println("ops:",opsFinal)
}

结果如下:

ops: 601082

 

代码如下:

package main

import (
	"fmt"
	"sort"
)

func main() {
	strs := []string{"c","a","b"}
	sort.Strings(strs)
	fmt.Println("strings:",strs)

	ints := []int{7,2,4}
	sort.Ints(ints)
	fmt.Println("ints:",ints)

	s := sort.IntsAreSorted(ints)
	fmt.Println("sorted",s)
}

结果如下:

strings: [a b c]
ints: [2 4 7]
sorted true

 

package main

import (
	"fmt"
	"sort"
)

type ByLength []string

func (s ByLength) Len() int{
	return len(s)
}

func (s ByLength) Less(i,j int) bool{
	return len(s[i])<len(s[j])
}

func (s ByLength) Swap(i,j int) {
	s[i], s[j] = s[j], s[i]
}

func main(){
	s := []string{"hanmingyu","hanmy","hmy"}
	sort.Sort(ByLength(s))
	fmt.Println(s)
}

结果如下:

[hmy hanmy hanmingyu]

 

  • Panic​​​​​​​
package main

import "os"

func main(){
	panic("a problem")

	_,err := os.Create("/tmp/file")
	if err != nil{
		panic(err)
	}
}

结果如下:

panic: a problem

goroutine 1 [running]:
main.main()
    D:/GOPATH/src/awesomeProject/example/main/main.go:6 +0x40

Process finished with exit code 2

 

  • Defer​​​​​​​

代码如下:

package main

import (
	"fmt"
	"os"
)

func main(){
	f := createFile("D:/GOPATH/src/awesomeProject/example/main/defer.txt")
	defer closeFile(f)
	writeFile(f)
}

func createFile(p string) *os.File{
	fmt.Println("creating")
	f,err := os.Create(p)
	if err!=nil{
		panic(err)
	}
	return f
}

func writeFile(f *os.File){
	fmt.Println("writing")
	fmt.Fprintln(f,"data")
}

func closeFile(f *os.File){
	fmt.Println("closing")
	f.Close()
}

结果如下:

creating
writing
closing

 

代码如下:

package main

import (
	"fmt"
	"strings"
)

//返回目标字符串 t 出现的的第一个索引位置,或者在没有匹配值时返回 -1。
func Index(vs []string, t string) int{
	for i,v := range vs{
		if v==t{
			return i
		}
	}
	return -1
}

//如果目标字符串 t 在这个切片中则返回 true。
func Include(vs []string, t string) bool{
	return Index(vs,t)>=0
}

//如果这些切片中的字符串有一个满足条件 f 则返回true。
func Any(vs []string, f func(string) bool) bool{
	for _,v := range vs{
		if f(v){
			return true
		}
	}
	return false
}

//如果切片中的所有字符串都满足条件 f 则返回 true。
func All(vs []string, f func(string) bool) bool{
	for _,v := range vs{
		if !f(v){
			return false
		}
	}
	return true
}

//返回一个包含所有切片中满足条件 f 的字符串的新切片。
func Filter(vs []string, f func(string) bool) []string{
	s := []string{}//s := make([]string,0)
	for _,v := range vs{
		if f(v){
			s = append(s,v)
		}
	}
	return s
}

//返回一个对原始切片中所有字符串执行函数 f 后的新切片。
func Map(vs []string, f func(string) string) []string{
	s := []string{}//s := make([]string,0)
	for _,v := range vs{
		s = append(s,f(v))
	}
	return s
}

func main() {

	var strs = []string{"peach", "apple", "pear", "plum"}
	fmt.Println(Index(strs, "pear"))
	fmt.Println(Include(strs, "grape"))
	fmt.Println(Any(strs, func(v string) bool {
		return strings.HasPrefix(v, "p")
	}))
	fmt.Println(All(strs, func(v string) bool {
		return strings.HasPrefix(v, "p")
	}))
	fmt.Println(Filter(strs, func(v string) bool {
		return strings.Contains(v, "e")
	}))

	fmt.Println(Map(strs, strings.ToUpper))
}

结果如下:

2
false
true
false
[peach apple pear]
[PEACH APPLE PEAR PLUM]

 

代码如下:

package main

import "fmt"
import s "strings"

var p = fmt.Println

func main(){
	p("Contains:  ", s.Contains("test", "es"))
	p("Count:     ", s.Count("test", "t"))
	p("HasPrefix: ", s.HasPrefix("test", "te"))
	p("HasSuffix: ", s.HasSuffix("test", "st"))
	p("Index:     ", s.Index("test", "e"))
	p("Join:      ", s.Join([]string{"a", "b"}, "-"))
	p("Repeat:    ", s.Repeat("a", 5))
	p("Replace:   ", s.Replace("foo", "o", "0", -1))
	p("Replace:   ", s.Replace("foo", "o", "0", 1))
	p("Split:     ", s.Split("a-b-c-d-e", "-"))
	p("ToLower:   ", s.ToLower("TEST"))
	p("ToUpper:   ", s.ToUpper("test"))
	p()
	p("Len: ", len("hello"))
	p("Char:", "hello"[1])
}

结果如下:

Contains:   true
Count:      2
HasPrefix:  true
HasSuffix:  true
Index:      1
Join:       a-b
Repeat:     aaaaa
Replace:    f00
Replace:    f0o
Split:      [a b c d e]
ToLower:    test
ToUpper:    TEST

Len:  5
Char: 101

 

package main

import (
	"fmt"
	"os"
)

type point struct {
	x,y int
}

func main(){

	//Go 为常规 Go 值的格式化设计提供了多种打印方式。例如,这里打印了 point 结构体的一个实例。
	p := point{1, 2}
	fmt.Printf("%v\n", p)

	//如果值是一个结构体,%+v 的格式化输出内容将包括结构体的字段名。
	fmt.Printf("%+v\n", p)

	//%#v 形式则输出这个值的 Go 语法表示。例如,值的运行源代码片段。
	fmt.Printf("%#v\n", p)

	//需要打印值的类型,使用 %T。
	fmt.Printf("%T\n", p)

	//格式化布尔值是简单的。
	fmt.Printf("%t\n", true)

	//格式化整形数有多种方式,使用 %d进行标准的十进制格式化。
	fmt.Printf("%d\n", 123)

	//这个输出二进制表示形式。
	fmt.Printf("%b\n", 14)

	//这个输出给定整数的对应字符。
	fmt.Printf("%c\n", 33)

	//%x 提供十六进制编码。
	fmt.Printf("%x\n", 456)

	//对于浮点型同样有很多的格式化选项。使用 %f 进行最基本的十进制格式化。
	fmt.Printf("%f\n", 78.9)

	//%e 和 %E 将浮点型格式化为(稍微有一点不同的)科学技科学记数法表示形式。
	fmt.Printf("%e\n", 123400000.0)
	fmt.Printf("%E\n", 123400000.0)

	//使用 %s 进行基本的字符串输出。
	fmt.Printf("%s\n", "\"string\"")

	//像 Go 源代码中那样带有双引号的输出,使用 %q。
	fmt.Printf("%q\n", "\"string\"")

	//和上面的整形数一样,%x 输出使用 base-16 编码的字符串,每个字节使用 2 个字符表示。
	fmt.Printf("%x\n", "hex this")

	//要输出一个指针的值,使用 %p。
	fmt.Printf("%p\n", &p)

	//当输出数字的时候,你将经常想要控制输出结果的宽度和精度,可以使用在 % 后面使用数字来控制输出宽度。默认结果使用右对齐并且通过空格来填充空白部分。
	fmt.Printf("|%6d|%6d|\n", 12, 345)

	//你也可以指定浮点型的输出宽度,同时也可以通过 宽度.精度 的语法来指定输出的精度。
	fmt.Printf("|%6.2f|%6.2f|\n", 1.2, 3.45)

	//要左对齐,使用 - 标志。
	fmt.Printf("|%-6.2f|%-6.2f|\n", 1.2, 3.45)

	//你也许也想控制字符串输出时的宽度,特别是要确保他们在类表格输出时的对齐。这是基本的右对齐宽度表示。
	fmt.Printf("|%6s|%6s|\n", "foo", "b")

	//要左对齐,和数字一样,使用 - 标志。
	fmt.Printf("|%-6s|%-6s|\n", "foo", "b")

	//到目前为止,我们已经看过 Printf了,它通过 os.Stdout输出格式化的字符串。Sprintf 则格式化并返回一个字符串而不带任何输出。
	s := fmt.Sprintf("a %s", "string")
	fmt.Println(s)

	//你可以使用 Fprintf 来格式化并输出到 io.Writers而不是 os.Stdout。
	fmt.Fprintf(os.Stderr, "an %s\n", "error")
}

结果如下:

{1 2}
an error
{x:1 y:2}
main.point{x:1, y:2}
main.point
true
123
1110
!
1c8
78.900000
1.234000e+08
1.234000E+08
"string"
"\"string\""
6865782074686973
0xc0420080d0
|    12|   345|
|  1.20|  3.45|
|1.20  |3.45  |
|   foo|     b|
|foo   |b     |
a string

 

代码如下:

package main

import (
	"bytes"
	"fmt"
	"regexp"
)

func main(){

	//这个测试一个字符串是否符合一个表达式。
	match, _ := regexp.MatchString("p([a-z]+)ch", "peach")
	fmt.Println(match)

	//上面我们是直接使用字符串,但是对于一些其他的正则任务,你需要 Compile 一个优化的 Regexp 结构体。
	r, _ := regexp.Compile("p([a-z]+)ch")

	//这个结构体有很多方法。这里是类似我们前面看到的一个匹配测试。
	fmt.Println(r.MatchString("peach"))

	//这是查找匹配字符串的。
	fmt.Println(r.FindString("peach punch"))

	//这个也是查找第一次匹配的字符串的,但是返回的匹配开始和结束位置索引,而不是匹配的内容。
	fmt.Println(r.FindStringIndex("peach punch"))

	//Submatch 返回完全匹配和局部匹配的字符串。例如,这里会返回 p([a-z]+)ch 和 `([a-z]+) 的信息。
    fmt.Println(r.FindStringSubmatch("peach punch"))

	//类似的,这个会返回完全匹配和局部匹配的索引位置。
    fmt.Println(r.FindStringSubmatchIndex("peach punch"))

	//带 All 的这个函数返回所有的匹配项,而不仅仅是首次匹配项。例如查找匹配表达式的所有项。
    fmt.Println(r.FindAllString("peach punch pinch", -1))

	//All 同样可以对应到上面的所有函数。
    fmt.Println(r.FindAllStringSubmatchIndex(
        "peach punch pinch", -1))

	//这个函数提供一个正整数来限制匹配次数。
    fmt.Println(r.FindAllString("peach punch pinch", 2))

	//上面的例子中,我们使用了字符串作为参数,并使用了如 MatchString 这样的方法。我们也可以提供 []byte参数并将 String 从函数命中去掉。
    fmt.Println(r.Match([]byte("peach")))

	//创建正则表示式常量时,可以使用 Compile 的变体MustCompile 。因为 Compile 返回两个值,不能用于常量。
    r = regexp.MustCompile("p([a-z]+)ch")
    fmt.Println(r)

    //regexp 包也可以用来替换部分字符串为其他值。
    fmt.Println(r.ReplaceAllString("a peach", "<fruit>"))

    //Func 变量允许传递匹配内容到一个给定的函数中,
    in := []byte("a peach")
    out := r.ReplaceAllFunc(in, bytes.ToUpper)
    fmt.Println(string(out))
}

结果如下:

true
true
peach
[0 5]
[peach ea]
[0 5 1 3]
[peach punch pinch]
[[0 5 1 3] [6 11 7 9] [12 17 13 15]]
[peach punch]
true
p([a-z]+)ch
a <fruit>
a PEACH

 

package main

import (
	"encoding/json"
	"fmt"
	"os"
)

type Response1 struct {
	Page   int
	Fruits []string
}

type Response2 struct {
	Page   int      `json:"page"`
	Fruits []string `json:"fruits"`
}

func main(){

	//首先我们来看一下基本数据类型到 JSON 字符串的编码过程。这里是一些原子值的例子。
	bolB, _ := json.Marshal(true)
	fmt.Println(string(bolB))
	intB, _ := json.Marshal(1)
	fmt.Println(string(intB))
	fltB, _ := json.Marshal(2.34)
	fmt.Println(string(fltB))
	strB, _ := json.Marshal("gopher")
	fmt.Println(string(strB))

	//这里是一些切片和 map 编码成 JSON 数组和对象的例子。
	slcD := []string{"apple", "peach", "pear"}
	slcB, _ := json.Marshal(slcD)
	fmt.Println(string(slcB))
	mapD := map[string]int{"apple": 5, "lettuce": 7}
	mapB, _ := json.Marshal(mapD)
	fmt.Println(string(mapB))

	//JSON 包可以自动的编码你的自定义类型。编码仅输出可导出的字段,并且默认使用他们的名字作为 JSON 数据的键。
	res1D := &Response1{
		Page:   1,
		Fruits: []string{"apple", "peach", "pear"}}
	res1B, _ := json.Marshal(res1D)
	fmt.Println(string(res1B))

	//你可以给结构字段声明标签来自定义编码的 JSON 数据键名称。在上面 Response2 的定义可以作为这个标签这个的一个例子。
	res2D := Response2{
		Page:   1,
		Fruits: []string{"apple", "peach", "pear"}}
	res2B, _ := json.Marshal(res2D)
	fmt.Println(string(res2B))

	//现在来看看解码 JSON 数据为 Go 值的过程。这里是一个普通数据结构的解码例子。
	byt := []byte(`{"num":6.13,"strs":["a","b"]}`)

	//我们需要提供一个 JSON 包可以存放解码数据的变量。这里的 map[string]interface{} 将保存一个 string 为键,值为任意值的map。
	var dat map[string]interface{}

	//这里就是实际的解码和相关的错误检查。
	if err := json.Unmarshal(byt, &dat); err != nil {
		panic(err)
	}
	fmt.Println(dat)

	//为了使用解码 map 中的值,我们需要将他们进行适当的类型转换。例如这里我们将 num 的值转换成 float64类型。
	num := dat["num"].(float64)
	fmt.Println(num)

	//访问嵌套的值需要一系列的转化。
	strs := dat["strs"].([]interface{})
	str1 := strs[0].(string)
	fmt.Println(str1)

	//我们也可以解码 JSON 值到自定义类型。这个功能的好处就是可以为我们的程序带来额外的类型安全加强,并且消除在访问数据时的类型断言。
	str := `{"page": 1, "fruits": ["apple", "peach"]}`
	res := &Response2{}
	json.Unmarshal([]byte(str), &res)
	fmt.Println(res)
	fmt.Println(res.Fruits[0])

	//在上面的例子中,我们经常使用 byte 和 string 作为使用标准输出时数据和 JSON 表示之间的中间值。我们也可以和os.Stdout 一样,直接将 JSON 编码直接输出至 os.Writer流中,或者作为 HTTP 响应体。
	enc := json.NewEncoder(os.Stdout)
	d := map[string]int{"apple": 5, "lettuce": 7}
	enc.Encode(d)
}

结果如下:

true
1
2.34
"gopher"
["apple","peach","pear"]
{"apple":5,"lettuce":7}
{"Page":1,"Fruits":["apple","peach","pear"]}
{"page":1,"fruits":["apple","peach","pear"]}
map[strs:[a b] num:6.13]
6.13
a
&{1 [apple peach]}
apple
{"apple":5,"lettuce":7}

 

代码如下:

package main

import (
	"fmt"
	"time"
)

func main(){
	p := fmt.Println

	//得到当前时间。
	now := time.Now()
	p(now)

	//通过提供年月日等信息,你可以构建一个 time。时间总是关联着位置信息,例如时区。
	then := time.Date(
		2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
	p(then)

	//你可以提取出时间的各个组成部分。
	p(then.Year())
	p(then.Month())
	p(then.Day())
	p(then.Hour())
	p(then.Minute())
	p(then.Second())
	p(then.Nanosecond())
	p(then.Location())

	//输出是星期一到日的 Weekday 也是支持的。
	p(then.Weekday())

	//这些方法来比较两个时间,分别测试一下是否是之前,之后或者是同一时刻,精确到秒。
	p(then.Before(now))
	p(then.After(now))
	p(then.Equal(now))

	//方法 Sub 返回一个 Duration 来表示两个时间点的间隔时间。
	diff := now.Sub(then)
	p(diff)

	//我们计算出不同单位下的时间长度值。
	p(diff.Hours())
	p(diff.Minutes())
	p(diff.Seconds())
	p(diff.Nanoseconds())

	//你可以使用 Add 将时间后移一个时间间隔,或者使用一个 - 来将时间前移一个时间间隔。
	p(then.Add(diff))
	p(then.Add(-diff))
}

结果如下:

2018-11-22 19:13:53.5523728 +0800 CST m=+0.005076301
2009-11-17 20:34:58.651387237 +0000 UTC
2009
November
17
20
34
58
651387237
UTC
Tuesday
true
false
false
78998h38m54.900985563s
78998.64858360711
4.739918915016426e+06
2.8439513490098554e+08
284395134900985563
2018-11-22 11:13:53.5523728 +0000 UTC
2000-11-13 05:56:03.750401674 +0000 UTC

 

代码如下:

package main

import (
	"fmt"
	"time"
)

func main(){

	//分别使用带 Unix 或者 UnixNano 的 time.Now来获取从自协调世界时起到现在的秒数或者纳秒数。
	now := time.Now()
	secs := now.Unix()
	nanos := now.UnixNano()
	fmt.Println(now)

	//注意 UnixMillis 是不存在的,所以要得到毫秒数的话,你要自己手动的从纳秒转化一下。
	millis := nanos / 1000000
	fmt.Println(secs)
	fmt.Println(millis)
	fmt.Println(nanos)

	//你也可以将协调世界时起的整数秒或者纳秒转化到相应的时间。
	fmt.Println(time.Unix(secs, 0))
	fmt.Println(time.Unix(0, nanos))
}

结果如下:

2018-11-22 19:18:49.4598433 +0800 CST m=+0.008107401
1542885529
1542885529459
1542885529459843300
2018-11-22 19:18:49 +0800 CST
2018-11-22 19:18:49.4598433 +0800 CST

 

代码如下:

package main

import (
	"fmt"
	"time"
)

func main(){
	p := fmt.Println

	//这里是一个基本的按照 RFC3339 进行格式化的例子,使用对应模式常量。
	t := time.Now()
	p(t.Format(time.RFC3339))

	//时间解析使用同 Format 相同的形式值。
	t1, e := time.Parse(
		time.RFC3339,
		"2012-11-01T22:08:41+00:00")
	p(t1)

	p(t.Format("3:04PM"))
	p(t.Format("Mon Jan _2 15:04:05 2006"))
	p(t.Format("2006-01-02T15:04:05.999999-07:00"))
	form := "3 04 PM"
	t2, e := time.Parse(form, "8 41 PM")
	p(t2)

	//对于纯数字表示的时间,你也可以使用标准的格式化字符串来提出出时间值得组成。
	fmt.Printf("%d-%02d-%02dT%02d:%02d:%02d-00:00\n",
		t.Year(), t.Month(), t.Day(),
		t.Hour(), t.Minute(), t.Second())

	//Parse 函数在输入的时间格式不正确是会返回一个错误。
	ansic := "Mon Jan _2 15:04:05 2006"
	_, e = time.Parse(ansic, "8:41PM")
	p(e)
}

结果如下:

2018-11-22T19:22:59+08:00
2012-11-01 22:08:41 +0000 +0000
7:22PM
Thu Nov 22 19:22:59 2018
2018-11-22T19:22:59.922421+08:00
0000-01-01 20:41:00 +0000 UTC
2018-11-22T19:22:59-00:00
parsing time "8:41PM" as "Mon Jan _2 15:04:05 2006": cannot parse "8:41PM" as "Mon"

 

代码如下:

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func main(){
	fmt.Print(rand.Intn(100), ",")
	fmt.Print(rand.Intn(100))
	fmt.Println()

	//rand.Float64 返回一个64位浮点数 f,0.0 <= f <= 1.0。
	fmt.Println(rand.Float64())

	//这个技巧可以用来生成其他范围的随机浮点数,例如5.0 <= f <= 10.0
	fmt.Print((rand.Float64()*5)+5, ",")
	fmt.Print((rand.Float64() * 5) + 5)
	fmt.Println()

	s1 := rand.NewSource(time.Now().UnixNano())
	r1 := rand.New(s1)

	//调用上面返回的 rand.Source 的函数和调用 rand 包中函数是相同的。
	fmt.Print(r1.Intn(100), ",")
	fmt.Print(r1.Intn(100))
	fmt.Println()

	//如果使用相同的种子生成的随机数生成器,将会产生相同的随机数序列。
	s2 := rand.NewSource(42)
	r2 := rand.New(s2)
	fmt.Print(r2.Intn(100), ",")
	fmt.Print(r2.Intn(100))
	fmt.Println()
	s3 := rand.NewSource(42)
	r3 := rand.New(s3)
	fmt.Print(r3.Intn(100), ",")
	fmt.Print(r3.Intn(100))
}

结果如下:

81,87
0.6645600532184904
7.1885709359349015,7.123187485356329
89,71
5,87
5,87

 

代码如下:

package main

import (
	"fmt"
	"strconv"
)

func main(){

	//使用 ParseFloat 解析浮点数,这里的 64 表示表示解析的数的位数。
	f, _ := strconv.ParseFloat("1.234", 64)
	fmt.Println(f)

	//在使用 ParseInt 解析整形数时,例子中的参数 0 表示自动推断字符串所表示的数字的进制。64 表示返回的整形数是以 64 位存储的。
	i, _ := strconv.ParseInt("123", 0, 64)
	fmt.Println(i)

	//ParseInt 会自动识别出十六进制数。
	d, _ := strconv.ParseInt("0x1c8", 0, 64)
	fmt.Println(d)

	//ParseUint 也是可用的。
	u, _ := strconv.ParseUint("789", 0, 64)
	fmt.Println(u)

	//Atoi 是一个基础的 10 进制整型数转换函数。
	k, _ := strconv.Atoi("135")
	fmt.Println(k)

	//在输入错误时,解析函数会返回一个错误。
	_, e := strconv.Atoi("wat")
	fmt.Println(e)
}

结果如下:

1.234
123
456
789
135
strconv.Atoi: parsing "wat": invalid syntax

 

代码如下:

package main

import (
	"fmt"
	"net/url"
	"strings"
)

func main(){

	//我们将解析这个 URL 示例,它包含了一个 scheme,认证信息,主机名,端口,路径,查询参数和片段。
	s := "postgres://user:pass@host.com:5432/path?k=v#f"

	//解析这个 URL 并确保解析没有出错。
	u, err := url.Parse(s)
	if err != nil {
		panic(err)
	}

	//直接访问 scheme。
	fmt.Println(u.Scheme)

	//User 包含了所有的认证信息,这里调用 Username和 Password 来获取独立值。
	fmt.Println(u.User)
	fmt.Println(u.User.Username())
	p, _ := u.User.Password()
	fmt.Println(p)

	//Host 同时包括主机名和端口信息,如过端口存在的话,使用 strings.Split() 从 Host 中手动提取端口。
	fmt.Println(u.Host)
	h := strings.Split(u.Host, ":")
	fmt.Println(h[0])
	fmt.Println(h[1])

	//这里我们提出路径和查询片段信息。
	fmt.Println(u.Path)
	fmt.Println(u.Fragment)

	//要得到字符串中的 k=v 这种格式的查询参数,可以使用 RawQuery 函数。你也可以将查询参数解析为一个map。
	fmt.Println(u.RawQuery)
	m, _ := url.ParseQuery(u.RawQuery)
	fmt.Println(m)
	fmt.Println(m["k"][0])
}

结果如下:

postgres
user:pass
user
pass
host.com:5432
host.com
5432
/path
f
k=v
map[k:[v]]
v

 

package main

import (
	"crypto/sha1"
	"fmt"
)

func main(){
	s := "i love cyj"

	h := sha1.New()
	h.Write([]byte(s))

	bs := h.Sum(nil)

	fmt.Println(s)
	fmt.Printf("%x\n",bs)
}

结果如下:

i love cyj
93452691dfa19ac3c4d58f3672da75ebdf348dc3

 

package main

import "fmt"
import b64 "encoding/base64"

func main(){

	//这是将要编解码的字符串。
	data := "i love cyj"

	//Go 同时支持标准的和 URL 兼容的 base64 格式。编码需要使用 []byte 类型的参数,所以要将字符串转成此类型。
	sEnc := b64.StdEncoding.EncodeToString([]byte(data))
	fmt.Println(sEnc)

	//解码可能会返回错误,如果不确定输入信息格式是否正确,那么,你就需要进行错误检查了。
	sDec, _ := b64.StdEncoding.DecodeString(sEnc)
	fmt.Println(string(sDec))
	fmt.Println()

	//使用 URL 兼容的 base64 格式进行编解码。
	uEnc := b64.URLEncoding.EncodeToString([]byte(data))
	fmt.Println(uEnc)
	uDec, _ := b64.URLEncoding.DecodeString(uEnc)
	fmt.Println(string(uDec))
}

结果如下:

aSBsb3ZlIGN5ag==
i love cyj

aSBsb3ZlIGN5ag==
i love cyj

 

代码如下:

package main

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"os"
)

func check(e error){
	if e!=nil{
		panic(e)
	}
}

func main(){
	
	//也许大部分基本的文件读取任务是将文件内容读取到内存中。
	dat,err := ioutil.ReadFile("D:/GOPATH/src/awesomeProject/example/main/defer.txt")
	check(err)
	fmt.Println(string(dat))

	//对于这个任务,从使用 os.Open打开一个文件获取一个 os.File 值开始。
	f,err := os.Open("D:/GOPATH/src/awesomeProject/example/main/defer.txt")
	check(err)

	//从文件开始位置读取一些字节。这里最多读取 6 个字节,并且这也是我们实际读取的字节数。
	b1 := make([]byte,6)
	n1,err := f.Read(b1)
	check(err)
	fmt.Printf("%d bytes: %s \n",n1,string(b1))

	//你也可以 Seek 到一个文件中已知的位置并从这个位置开始进行读取。
	o2,err := f.Seek(7,0)
	check(err)
	b2 := make([]byte,3)
	n2,err := f.Read(b2)
	check(err)
	fmt.Printf("%d bytes @ %d: %s\n",n2,o2,string(b2))

	//io 包提供了一些可以帮助我们进行文件读取的函数。
	o3,err := f.Seek(7,0)
	check(err)
	b3 := make([]byte,3)
	n3,err := io.ReadAtLeast(f,b3,3)
	check(err)
	fmt.Printf("%d bytes @ %d: %s\n",n3,o3,string(b3))

	//没有内置的回转支持,但是使用 Seek(0, 0) 实现。
	_,err = f.Seek(0,0)
	check(err)

	//bufio 包实现了带缓冲的读取,这不仅对有很多小的读取操作的能提升性能,也提供了很多附加的读取函数。
	r4 := bufio.NewReader(f)
	b4,err := r4.Peek(10)
	check(err)
	fmt.Printf("10 bytes: %s\n",string(b4))

	//任务结束后要关闭这个文件(通常这个操作应该在 Open操作后立即使用 defer 来完成)。
	f.Close()
}

结果如下:

i love cyj
6 bytes: i love 
3 bytes @ 7: cyj
3 bytes @ 7: cyj
10 bytes: i love cyj

 

代码如下:

package main

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"os"
)

func check(e error){
	if e!=nil{
		panic(e)
	}
}

func main(){

	//开始,这里是展示如写入一个字符串(或者只是一些字节)到一个文件。
	d1 := []byte("hello\nworld\n")
	err := ioutil.WriteFile("D:/GOPATH/src/awesomeProject/example/main/defer.txt",d1,0644)
	check(err)

	//对于更细粒度的写入,先打开一个文件。
	f,err := os.Create("D:/GOPATH/src/awesomeProject/example/main/dat.txt")
	check(err)

	//打开文件后,习惯立即使用 defer 调用文件的 Close操作。
	defer f.Close()

	//你可以写入你想写入的字节切片
	d2 := []byte("i love cyj\n")
	n2,err := f.Write(d2)
	check(err)
	fmt.Printf("write %d bytes\n",n2)

	//WriteString 也是可用的。
	n3,err := f.WriteString("cyj love me too\n")
	check(err)
	fmt.Printf("write %d bytes\n",n3)

	//调用 Sync 来将缓冲区的信息写入磁盘。
	f.Sync()

	//bufio 提供了和我们前面看到的带缓冲的读取器一样的带缓冲的写入器。
	w := bufio.NewWriter(f)
	n4,err := w.WriteString("buffered\n")
	check(err)
	fmt.Printf("write %d bytes\n",n4)

	//使用 Flush 来确保所有缓存的操作已写入底层写入器。
	w.Flush()
}

结果如下:

write 11 bytes
write 16 bytes
write 9 bytes

 

代码如下:

package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

func main(){
	scanner := bufio.NewScanner(os.Stdin)

	for scanner.Scan(){
		//Text 返回当前的 token,现在是输入的下一行。
		ucl := strings.ToUpper(scanner.Text())
		//写出大写的行。
		fmt.Println(ucl)
	}

	//检查 Scan 的错误。文件结束符是可以接受的,并且不会被 Scan 当作一个错误。
	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		os.Exit(1)
	}
}

结果如下:

hello
HELLO
world
WORLD

 

 

代码如下:

package main

import (
	"fmt"
	"os"
	"strings"
)

func main() {

	//使用 os.Setenv 来设置一个键值队。使用 os.Getenv获取一个键对应的值。如果键不存在,将会返回一个空字符串。
	os.Setenv("FOO", "1")
	fmt.Println("FOO:", os.Getenv("FOO"))
	fmt.Println("BAR:", os.Getenv("BAR"))

	//使用 os.Environ 来列出所有环境变量键值队。这个函数会返回一个 KEY=value 形式的字符串切片。
	fmt.Println()
	for _, e := range os.Environ() {
		pair := strings.Split(e, "=")
		fmt.Println(pair[0])
	}
}

结果如下:

FOO: 1
BAR: 


ALLUSERSPROFILE
APPDATA
CommonProgramFiles
CommonProgramFiles(x86)
CommonProgramW6432
COMPUTERNAME
ComSpec
configsetroot
FOO
FPS_BROWSER_APP_PROFILE_STRING
FPS_BROWSER_USER_PROFILE_STRING
GOPATH
GOROOT
HOMEDRIVE
HOMEPATH
LOCALAPPDATA
LOGONSERVER
NUMBER_OF_PROCESSORS
OneDrive
OS
Path
PATHEXT
PROCESSOR_ARCHITECTURE
PROCESSOR_IDENTIFIER
PROCESSOR_LEVEL
PROCESSOR_REVISION
ProgramData
ProgramFiles
ProgramFiles(x86)
ProgramW6432
PSModulePath
PUBLIC
SESSIONNAME
SystemDrive
SystemRoot
TEMP
TMP
USERDOMAIN
USERDOMAIN_ROAMINGPROFILE
USERNAME
USERPROFILE
windir

 

代码如下:

package main

import (
	"fmt"
	"os"
)

func main() {
	//当使用 os.Exit 时 defer 将不会 执行,所以这里的 fmt.Println将永远不会被调用。
	defer fmt.Println("!")
	
	//退出并且退出状态为 3。
	os.Exit(3)
}

结果如下:


Process finished with exit code 3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值