Go笔记

1.切片
func main(){
var num []int = []int{0,0,0,0,0}
fmt.Println(num)
modifyArray(num)
fmt.Println(num)
}

func modifyArray(ar []int){//传递的只是切片,底层还是指向同一个数组
ar[1] = 22
fmt.Printf("ar[1] : %d\n",ar[1])
}

运行结果:
[0 0 0 0 0]
ar[1] : 22
[0 22 0 0 0]


2.数组
func main(){
var num [5]int
fmt.Println(num)
modifyArray(num)
fmt.Println(num)
}

func modifyArray(ar [5]int){//数组传递参数是值拷贝
ar[1] = 22
fmt.Printf("ar[1] : %d\n",ar[1])
}

运行结果:
[0 0 0 0 0]
ar[1] : 22
[0 0 0 0 0]


3.指针
var p *int
//fmt.Println("p:",*p) 错误,panic: runtime error: invalid memory address or nil pointer dereference
fmt.Println("p:",p)
fmt.Printf("p:%x\n",p)
fmt.Printf("p:",p)

运行结果:
p: <nil>
p:0
p:%!(EXTRA *int=<nil>)


4.映射(引用类型)
(make只用来创建slice,map,channel,并返回一个初始化的(而不是置零)类型为T的值(而不是*T),之所以有所不同,是因为这三个类型的背后引用了使用前必须初始化的数据结构)
var m map[string]int
m["hello"] = 10
fmt.Println(m["hello"])

运行结果:
panic: assignment to entry in nil map

正确方式1
var m map[string]int
m = make(map[string]int)
m["hello"] = 10
fmt.Println(m["hello"])

运行结果:
10


正确方式2
var m map[string]int = map[string]int{}
m["hello"] = 10
fmt.Println(m["hello"])

运行结果:
10


5.Type switch(类型switch)与Type assertions(类型断言)

func main(){
	var i int = 10
	TypeOf(i)
	var d float64
	TypeOf(d)
	var value interface{}
	value = "abcdefg"
	//返回的是值和时候发生错误的bool变量
	str, ok := value.(string)//value必须为接口类型,断言是否是string类型
	if ok {
    		fmt.Printf("string value is: %q\n", str)
	} else {
    		fmt.Printf("value is not a string\n")
	}
}

func TypeOf(a interface{}){
	//返回的是类型
	switch t := a.(type){ //类型判断,a必须为接口类型, (t := a.(type)放在switch外为什么不行?)
		case int:
			fmt.Printf("%d is %T\n",a,t)
		break;
		default:
			fmt.Printf("type : %T\n",t)
	}
}

运行结果:
10 is int
type : float64


6.闭包

func intSeq()func()int{
	i := 0
	return func()int{
		i++
		return i
	}
}

func main(){
	intNext := intSeq()
	fmt.Println(intNext())
	fmt.Println(intNext())
	fmt.Println(intNext())
	numNext := intSeq()
	fmt.Println(numNext())
	fmt.Println(numNext())
}


运行结果:

1
2
3
1
2


7.json与对象互转(json的key为变量名)

import "fmt"
import "encoding/json"

type Position struct{
	X,Y,Z int
}

type Person struct{
	Name,Sex string
	Age int
	Posi Position
}

func main(){
	
	position := Position{10,20,30}
	person := Person{"zhang","male",18,position}
	position2 := Position{40,50,60}
	person2 := Person{"li","female",19,position2}
	//对象转json
	var slice = make([]Person ,2)
	slice[0] = person
	slice[1] = person2
	fmt.Printf("slice = %v\n",slice)
	data,err := json.Marshal(slice)
	if err != nil{
		fmt.Printf("err = %v\n",err)
		return
	}
	fmt.Printf("data = %s\n",data)
	//json转对象
	var dslice = make([]Person,1)
	err = json.Unmarshal(data,&dslice)
	if err != nil{
		fmt.Printf("err = %v\n",err)
		return
	}
	fmt.Printf("dslice = %v\n",dslice)
}


运行结果:

slice = [{zhang male 18 {10 20 30}} {li female 19 {40 50 60}}]
data = [{"Name":"zhang","Sex":"male","Age":18,"Posi":{"X":10,"Y":20,"Z":30}},{"Name":"li","Sex":"female","Age":19,"Posi":{"X":40,"Y":50,"Z":60}}]
dslice = [{zhang male 18 {10 20 30}} {li female 19 {40 50 60}}]


8.json与对象互转(json的key自定义)

import "fmt"
import "encoding/json"

type Position struct{
	X int `json:"x"`
	Y int `json:"y"`
	Z int `json:"z"`
}

type Person struct{
	Name string `json:"name"`
	Sex string `json:"sex"`
	Age int `json:"age"`
	Posi Position `json:"position"`
}

func main(){
	
	position := Position{10,20,30}
	person := Person{"zhang","male",18,position}
	position2 := Position{40,50,60}
	person2 := Person{"li","female",19,position2}
	//对象转json
	var slice = make([]Person ,2)
	slice[0] = person
	slice[1] = person2
	fmt.Printf("slice = %v\n",slice)
	data,err := json.Marshal(slice)
	if err != nil{
		fmt.Printf("err = %v\n",err)
		return
	}
	fmt.Printf("data = %s\n",data)
	//json转对象
	var dslice = make([]Person,1)
	err = json.Unmarshal(data,&dslice)
	if err != nil{
		fmt.Printf("err = %v\n",err)
		return
	}
	fmt.Printf("dslice = %v\n",dslice)
}


运行结果:

slice = [{zhang male 18 {10 20 30}} {li female 19 {40 50 60}}]
data = [{"name":"zhang","sex":"male","age":18,"position":{"x":10,"y":20,"z":30}},{"name":"li","sex":"female","age":19,"position":{"x":40,"y":50,"z":60}}]
dslice = [{zhang male 18 {10 20 30}} {li female 19 {40 50 60}}]


9.Go工作池

import (
	"fmt"
	"time"
)

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

func main(){
	jobs := make(chan int ,100)
	results := make(chan int ,100)
	for i := 1 ;i <= 3; i++{
		go worker(i,jobs,results)
	}
	for i := 1;i<=5;i++{
		jobs <- i
	}
	close(jobs)
	for i := 1;i<=5;i++{
		fmt.Println(<- results)
	}
	//如果使用range循环results,如何停止(关闭)results channel ?
}


运行结果:

worker 3 start job 1
worker 2 start job 3
worker 1 start job 2
worker 1 finish job 2
worker 1 start job 4
worker 3 finish job 1
worker 3 start job 5
2
1
worker 2 finish job 3
3
worker 3 finish job 5
5
worker 1 finish job 4
4


10.atomic原子操作  
(用原子操作来替换mutex锁

其主要原因是,原子操作由底层硬件支持,而锁则由操作系统提供的API实现。若实现相同的功能,前者通常会更有效率。)

import "fmt"
import "sync/atomic"

func main(){
	var ops uint64 = 0
	var opt uint64 = 0
	var count = make(chan int ,50)
	for i:=0;i<50;i++{
		go func(){
			for j:=0;j<1000;j++{
				atomic.AddUint64(&ops,1)  //原子操作
				opt++   //非原子操作
			}
			count<-i		
		}()
	}
	for i:=0;i<50;i++{
		<-count
	}
	fmt.Println("ops:",ops,"opt:",opt)
}


运行结果:

ops: 50000 opt: 21176


11.mutex实现线程安全(显式锁定互斥体同步对多个goroutine的共享状态的访问)
(
go 语言的map是引用传递的、如果多个goroutine同时读写,必然导致冲突,所以一般我们在并发操作map的时候,一定要加锁,但是如果map里的value是还是map,那么并发操作这个value- map是不是也一样回引起冲突呢?答案是:是的,go里所有map的并发操作都需要加锁,这样才不会引起冲突,见如下代码。我对map td操作加了锁,对得到的value-map进行了写操作,没有加锁,通过go run -race aa.go 依然可以检测到冲突,所以结论就是:并发读写操作go语言的任何一个map都需要加锁,这样才能防止冲突。
go 自带竞争检测机制调用如下命令:
go run -race mutex.go
./mutex

)

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

func main(){
	var state = make(map[int]int)
	var mutex = &sync.Mutex{}
	var readOps uint64 = 0
	var writeOps uint64 = 0
	for i:=0;i<100;i++{
		go func(){
			total := 0
			for{
				key := rand.Intn(5)
				mutex.Lock()  //在并发环境中,对map读写操作如果不加锁就会报错
				total += state[key]
				mutex.Unlock()  //在并发环境中,对map读写操作如果不加锁就会报错
				atomic.AddUint64(&readOps,1)
				time.Sleep(time.Millisecond)
			}
		}()
	}
	for w:=0;w<10;w++{
		go func(){
			for{
				key := rand.Intn(5)
				val := rand.Intn(100)
				mutex.Lock() //在并发环境中,对map读写操作如果不加锁就会报错
				state[key] = val
				mutex.Unlock() //在并发环境中,对map读写操作如果不加锁就会报错
				atomic.AddUint64(&writeOps,1)
				time.Sleep(time.Millisecond)
			}
		}()
	}
	time.Sleep(time.Second)
	readOpsFinal := atomic.LoadUint64(&readOps)
	fmt.Println("readOps:",readOpsFinal)
	writeOpsFinal := atomic.LoadUint64(&writeOps)
	fmt.Println("writeOps:",writeOpsFinal)
	mutex.Lock()
	fmt.Println("state:",state)
	mutex.Unlock()
}


运行结果:

readOps: 92963
writeOps: 9188
state: map[0:45 3:60 2:12 4:50 1:51]


12.chan实现线程安全(goroutine和通道的内置同步功能来实现共享状态的访问)

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

type readOps struct{
	key int
	resp chan int
}

type writeOps struct{
	key int 
	val int 
	resp chan bool
}

func main(){
	reads := make(chan *readOps)
	writes := make(chan *writeOps)

	var readNum uint64 = 0
	var writeNum uint64 = 0

	for i:=0;i<100;i++{
		go func(){
			state := make(map[int]int)
			for{
				select{
					case r := <- reads:
						r.resp <- state[r.key]
						break
					case d := <- writes:
						state[d.key] = d.val
						d.resp <- true
						break
				}
			}
		}()
	}
	for i:=0;i<100;i++{
		go func(){
			for{
				read := &readOps{
						key:rand.Intn(5),
						resp:make(chan int)}//}不能换行
				reads <- read
				<- read.resp
				atomic.AddUint64(&readNum,1)
				time.Sleep(time.Millisecond)
			}
		}()
	}
	for i:=0;i<10;i++{
		go func(){
			for{
				write := &writeOps{
						key : rand.Intn(5),
						val : rand.Intn(100),
						resp: make(chan bool)}//}不能换行
				writes <- write
				<- write.resp
				atomic.AddUint64(&writeNum,1)
				time.Sleep(time.Millisecond)
			}
		}()
	}
	time.Sleep(time.Second)
	readTemp := atomic.LoadUint64(&readNum)
	fmt.Println("readNum",readTemp)
	writeTemp := atomic.LoadUint64(&writeNum)
	fmt.Println("writeNum",writeTemp)
}


运行结果:

readNum 90960
writeNum 9095


13.排序,自定义函数排序(自定义的类型数组排序实现)

(自定义函数进行排序,我们需要一个相应的类型,该类型需要实现sort.Interface接口的Len、Less、Swap方法)

import "fmt"
import "sort"

type ByLenth []string

func (b ByLenth) Len() int{//长度
	return len(b)
}

func (b ByLenth) Less(i,j int) bool{//自定义排序逻辑
	return len(b[i]) < len(b[j])
}

func (b ByLenth) Swap(i,j int){//交换
	b[i],b[j] = b[j],b[i]
}

func main(){
	b := ByLenth{"abcdef","123","wwww"}
	sort.Sort(b)
	fmt.Println(b)
}


运行结果:

[123 wwww abcdef]


14.defer、io

(defer:延迟操作,io:文件操作)

import "fmt"
import "os"
import "io/ioutil"

func main(){
	//write
	//f := createFile("defer-file.txt")
	//defer closeFile(f)
	//writeFile(f)

	//read
	f := openFile("defer-file.txt")
	defer closeFile(f)
	readFile(f)
}

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

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

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

func readFile(f *os.File){
	fmt.Println("reading")
	b,err := ioutil.ReadAll(f)
	if err != nil{
		panic(err)
	}
	fmt.Println(string(b))
}

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


运行结果:

creating
writing
closing

creating
reading
data...


closing


15.字符串集合函数

import "fmt"
import "strings"

func Index(vs []string,s string) int{
	for i,v := range vs{
		if v == s {
			return i
		}
	}
	return -1
}

func Include(vs []string,s string) bool{
	return Index(vs,s) >= 0
}

func Any(vs []string,f func (s string) bool)bool{
	for _,v := range vs{
		if f(v){
			return true
		}
	}
	return false
}

func All(vs []string,f func(s string)bool) bool{
	for _,v := range vs{
		if !f(v){
			return false
		}
	}
	return true
}

func Filter(vs []string,f func(s string)bool) []string{
	tmp := make([]string,0)
	for _,v := range vs{
		if f(v){
			tmp = append(tmp,v)
		}
	}
	return tmp
}

func Map(vs []string,f func(s string)string) []string{
	tmp := make([]string,len(vs))
	for i,v := range vs{
		tmp[i] = f(v)
	}
	return tmp
}

func main(){
	var strs = []string{"peach","apple","android","pear","wa"}
	fmt.Println(Index(strs,"android"))
	fmt.Println(Index(strs,"Android"))
	fmt.Println(Include(strs,"android"))
	fmt.Println(Include(strs,"Android"))
	fmt.Println(Any(strs,func (s string) bool{
		return strings.HasPrefix(s,"a")
	}))
	fmt.Println(Any(strs,func (s string) bool{
		return strings.HasPrefix(s,"A")
	}))
	fmt.Println(All(strs,func (s string) bool{
		return strings.HasPrefix(s,"a")
	}))
	fmt.Println(All(strs,func (s string) bool{
		return strings.HasPrefix(s,"A")
	}))
	fmt.Println(Filter(strs,func (s string)bool{
		return strings.Contains(s,"a")
	}))
	fmt.Println(Filter(strs,func (s string)bool{
		return strings.Contains(s,"A")
	}))
	fmt.Println(Map(strs,strings.ToUpper))
}


运行结果:

2
-1
true
false
true
false
false
false
[peach apple android pear wa]
[]
[PEACH APPLE ANDROID PEAR WA]


16.math/rand随机数

import "math/rand"
import "fmt"
import "time"

func main(){
	//rand.Float64()  返回一个64位浮点数 f,0.0 <= f < 1.0
	for i:=0;i<10;i++{
		//rand.Seed(time.Now().Unix())//秒(循环10次,每次获取的秒都是一样,所以生成的随机数也一样)
		rand.Seed(time.Now().UnixNano())//纳秒(循环10次,每次获取的纳秒都是不一样的,所以生成的随机数都是不一样的)
		//如果设置的种子是一样的话,每次生成的随机数就是一样的,
		//如果不设置种子,每次生成的随机数也是不一样的
		fmt.Println(rand.Intn(100))
	}
}


运行结果:

Unix():
80
80
80
80
80
80
80
80
80
80

UnixNano():
72
58
43
83
46
71
19
55
94
46


17.时间日期示例
(
GMT 是“Greenwich Mean Time”的缩写,中文叫“格林尼治标准时间”,是英国的标准时间,也是世界各地时间的参考标准。中英两国的标准时差为8个小时,即英国的当地时间比中国的北京时间晚8小时。
UTC:全球标准时间(Coordinated Universal Time),由世界时间标准设定的时间,原先也被称为格林威治标准时间或者GMT。UTC+800:UTC是零时区,即格林威治标准时间;800的含义是8:00即8个小时0分;UTC+800是指比格林威治标准时间提前8个小时,应当是东八区的时间,也就是北京时间。
CST可以为如下4个不同的时区的缩写:
美国中部时间:Central Standard Time (USA) UT-6:00  (标准时间推迟6小时)
澳大利亚中部时间:Central Standard Time (Australia) UT+9:30  (标准时间提前9小时30分)
中国标准时间:China Standard Time UT+8:00   (标准时间提前8小时)(如果当前是中国标准时间转到美国中部时间就得推迟8+6=14小时)
古巴标准时间:Cuba Standard Time UT-4:00   (标准时间推迟4小时)
)

运行结果:

2017-12-20 10:24:35.370743684 +0800 CST m=+0.0001655262009-11-17 20:34:58.651387237 +0000 UTCNovember17203458651387237UTCTuesdaytruefalsefalse70901h49m36.719356447s70901.82686648794.254109611989274e+062.5524657671935645e+082552465767193564472017-12-20 02:24:35.370743684 +0000 UTC2001-10-16 14:45:21.93203079 +0000 UTC

18.epoch示例

import "fmt"
import "time"

func main(){
	now := time.Now()
	secs := now.Unix()
	nanos := now.UnixNano()
	fmt.Println(now)

	millis := nanos / 1000000
	fmt.Println(secs)
	fmt.Println(millis)
	fmt.Println(nanos)

	fmt.Println(time.Unix(secs,0))
	fmt.Println(time.Unix(0,nanos))
}


运行结果:

2017-12-20 10:31:42.75317838 +0800 CST m=+0.000160436
1513737102
1513737102753
1513737102753178380
2017-12-20 10:31:42 +0800 CST
2017-12-20 10:31:42.75317838 +0800 CST


19.URL解析

import "fmt"
import "net"
import "net/url"

func main(){
	//s := "postgres://user:pass@host.com:5432/path?k=v#f"
	s := "scheme://user:pass@host:port/path?query=fragment1#fragment2"
	u,err := url.Parse(s)
	if err != nil{
		panic(err)
	}
	fmt.Println(u.Scheme)
	fmt.Println(u.User)
	fmt.Println(u.User.Username())
	p,_ := u.User.Password()
	fmt.Println(p)
	fmt.Println(u.Host)
	host,port,_ := net.SplitHostPort(u.Host)
	fmt.Println(host)
	fmt.Println(port)
	fmt.Println(u.Path)
	fmt.Println(u.Fragment)
	fmt.Println(u.RawQuery)
	m,_ := url.ParseQuery(u.RawQuery)
	fmt.Println(m)
	fmt.Println(m["query"][0])
}


运行结果:

scheme
user:pass
user
pass
host:port
host
port
/path
fragment2
query=fragment1
map[query:[fragment1]]
fragment1


20.sha1哈希值([]byte)

import "crypto/sha1"
import "fmt"

func main(){
	s := "this is sha1"
	h := sha1.New()
	h.Write([]byte(s))
	bs := h.Sum(nil)
	fmt.Println(s)
	fmt.Printf("%x\n",bs)
}


运行结果:

this is sha1
3de76d4897cfdfd9a44c66d124640a0d943ed592


21.sha1哈希值(File)

import "crypto/sha1"
import "fmt"
import "os"
import "io"

func main(){
	file,err := os.Open("defer-file.txt")
	if err != nil {
		return
	}
	defer file.Close()
	h := sha1.New()
	_,erro := io.Copy(h,file)
	if erro != nil{
		return
	}
	fmt.Printf("%x\n",h.Sum(nil))
}


运行结果:

cc9983a1d0f02dc9281924ccd6ecf6cebfee0477


22.base64编码/解码

import b64 "encoding/base64"
import "fmt"

func main(){
	data := "abc123!?$*&()'-=@~"
	sEnc := b64.StdEncoding.EncodeToString([]byte(data))
	fmt.Println(sEnc)
	sDec,_ := b64.StdEncoding.DecodeString(sEnc)
	fmt.Println(string(sDec))
	
	uEnc := b64.URLEncoding.EncodeToString([]byte(data))
	fmt.Println(uEnc)
	uDec,_ := b64.URLEncoding.DecodeString(uEnc)
	fmt.Println(string(uDec))
}


运行结果:

YWJjMTIzIT8kKiYoKSctPUB+
abc123!?$*&()'-=@~
YWJjMTIzIT8kKiYoKSctPUB-
abc123!?$*&()'-=@~


23.文件读取
(
//读文件使用os.Open()
//写文件使用os.OpenFile()

)

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

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

var path = "defer-file.txt"
//文件内容:
/**
data...abcdefghigklmn
abc
*/

func main(){
	//readFile()
	//readAll()
	//read()
	//readNoBuf()
	readBuf()
}

func readBuf(){
	fi,err := os.Open(path)
	check(err)
	defer fi.Close()
	r := bufio.NewReader(fi)
	chunks := make([]byte,1024,1024)
	buf := make([]byte,1024)
	for{
		n,err := r.Read(buf)
		if err == io.EOF{//先检测err是否是EOF,是说明已经结束
			break
		}
		check(err)
		chunks = append(chunks,buf[:n]...)
	}
	fmt.Println(string(chunks))
}

func readNoBuf(){
	fi,err := os.Open(path)
	check(err)
	defer fi.Close()
	chunks := make([]byte,1024,1024)
	buf := make([]byte,1024)
	for{
		n,err := fi.Read(buf)
		if err != nil && err != io.EOF {
			panic(err)
		}
		if 0 == n{
			break
		}
		chunks = append(chunks,buf[:n]...)
	}
	fmt.Println(string(chunks))
}

func read(){
	f,err := os.Open(path)
	check(err)
	bys := make([]byte,5)
	n,err := f.Read(bys)//直接读取,只读取5个字节
	check(err)
	fmt.Printf("%d bytes : %s\n",n,string(bys)) //5 bytes : data.
	
	o2,err := f.Seek(6,0)
	check(err)
	bys2 := make([]byte,2)
	//函数就是从读取器中读取数据放到我们的buf中,限定了最小的读取字节数,如果我们读取的数据小于最小读取	器,譬如你设定min的值是8,但是你读取的数据字节数是5就会返回一个`io.ErrUnexpectedEOF`,如果大于就会返回`io.ErrShortBuffer`,读取完毕会有`io.EOF`~~
	n2,err := io.ReadAtLeast(f,bys2,2)
	check(err)
	fmt.Printf("%d bytes @ %d : %s\n",n2,o2,string(bys2))//2 bytes @ 6 : .a
	
	_,err = f.Seek(0,0)
	check(err)
	r3 := bufio.NewReader(f)//封装缓存读取
	 Peek 返回缓存的一个切片,该切片引用缓存中前 n 字节数据
	// 该操作不会将数据读出,只是引用
	// 引用的数据在下一次读取操作之前是有效的
	// 如果引用的数据长度小于 n,则返回一个错误信息
	// 如果 n 大于缓存的总大小,则返回 ErrBufferFull
	// 通过 Peek 的返回值,可以修改缓存中的数据
	// 但是不能修改底层 io.Reader 中的数据
	bys3,err := r3.Peek(5)
	check(err)
	fmt.Printf("5 bytes: %s\n",string(bys3))//5 bytes: data.
	f.Close()
}

func readAll(){
	f,err := os.Open(path)
	check(err)
	bys,err := ioutil.ReadAll(f)//速度快(系统封装好的总比自己写的速度要快)
	check(err)
	fmt.Println(string(bys))
}

func readFile(){
	data,err := ioutil.ReadFile("defer-file.txt")//速度较快(系统封装好的总比自己写的速度要快)
	check(err)
	fmt.Println(string(data))
}


24.文件写入

(//读文件使用os.Open()//写文件使用os.OpenFile())

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

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

/**
*判断文件是否存在,存在返回true,不存在返回false
*/
func checkFileIsExist(file string)bool{
	if _,err := os.Stat(file);os.IsNotExist(err){
		return false
	}
	return true
}

var path = "defer-file.txt"
var content = "hello world...\n"

//io,ioutil,File,Writer
func main(){
	//writeFile()
	//writeString()
	//writeNoBuf()
	writeBuf()
}

func writeBuf(){
	f,err := os.Create(path)
	check(err)
	defer f.Close()
	w := bufio.NewWriter(f)
	n,err := w.WriteString(content)
	check(err)
	fmt.Printf("write %d bytes\n",n)
	//刷新写入任何缓冲的数据基础io.writer
	//File 用Sync()
	//Writer用Flush()
	w.Flush()
}

func writeNoBuf(){
	f,err := os.Create(path)
	check(err)
	defer f.Close()
	n,err := f.Write([]byte("write...\n"))
	check(err)
	fmt.Printf("write %d bytes\n",n)
	n2,err := f.WriteString(content)
	check(err)
	fmt.Printf("write %d bytes\n",n2)
	//同步将文件的当前内容提交到稳定存储。
	//通常,这意味着将文件系统最近写入数据的内存副本刷新到磁盘。
	//File 用Sync()
	//Writer用Flush()
	f.Sync()
}	

func writeString(){
	var f *os.File
	var err error
	if checkFileIsExist(path){
		f,err = os.OpenFile(path,os.O_APPEND|os.O_WRONLY,0666)
		fmt.Println("文件存在")
	}else{
		f,err = os.Create(path)
		fmt.Println("文件不存在")
	}
	check(err)
	n,err := io.WriteString(f,content)
	check(err)
	fmt.Printf("write %d bytes\n",n)
}

func writeFile(){
	bys := []byte("hello world !\n")
	err := ioutil.WriteFile(path,bys,0666)
	check(err)
}


25.标准输入,行过滤器

import "bufio"
import "fmt"
import "os"
import "strings"

func main(){
	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan(){
		ucl := strings.ToUpper(scanner.Text())
		fmt.Println(ucl)
		if ucl == "BREAK"{
			break
		}
	}
	if err := scanner.Err();err != nil{
		fmt.Println(os.Stderr,"error:",err)
		os.Exit(1)
	}
}




运行结果:
hello
HELLO
break
BREAK


26.命令行参数

import "os"
import "fmt"

func main(){
	argsWithProg := os.Args
	argsWithoutProg := os.Args[1:]
	arg := os.Args[3]
	fmt.Println(argsWithProg)
	fmt.Println(argsWithoutProg)
	fmt.Println(arg)
}


运行结果:

 go run command-line-arguments.go a b c d e f g
[/tmp/go-build229759270/command-line-arguments/_obj/exe/command-line-arguments a b c d e f g]
[a b c d e f g]
c


27.命令行标志flag

import "flag"
import "fmt"

func main(){
	wordPtr := flag.String("word","foo","a string")
	numPtr := flag.Int("num",86,"a int")
	boolPtr := flag.Bool("fork",false,"a bool")
	var svar string
	flag.StringVar(&svar,"svar","bar","a string var")
	flag.Parse()
	fmt.Println("word:",*wordPtr)
	fmt.Println("num:",*numPtr)
	fmt.Println("fork:",*boolPtr)
	fmt.Println("svar:",svar)
	fmt.Println("tail:",flag.Args())
}


运行结果:

$ go build command-line-flags.go 
//如果你省略一个标志,那么这个标志的值自动的设定为他的默认值
$ ./command-line-flags -word=opt -num=86 -fork=true svar=flag
word: opt
num: 86
fork: true
svar: bar
tail: [svar=flag]
//位置参数可以出现在任何标志后面。
$ ./command-line-flags -word=opt a b c
word: opt
num: 86
fork: false
svar: bar
tail: [a b c]
//flag 包需要所有的标志出现位置参数之前(否则,这个标志将会被解析为位置参数)
$ ./command-line-flags -word=opt a b c -num=12
word: opt
num: 86
fork: false
svar: bar
tail: [a b c -num=12]
//使用 -h 或者 --help 标志来得到自动生成的这个命令行程序的帮助文本。
$ ./command-line-flags -h
Usage of ./command-line-flags:
  -fork
    a bool
  -num int
    a int (default 86)
  -svar string
    a string var (default "bar")
  -word string
    a string (default "foo")
//如果你提供一个没有使用 flag 包指定的标志,程序会输出一个错误信息,并再次显示帮助文本。
$ ./command-line-flags -wat
flag provided but not defined: -wat
Usage of ./command-line-flags:
  -fork
    a bool
  -num int
    a int (default 86)
  -svar string
    a string var (default "bar")
  -word string
    a string (default "foo")


28.环境变量

(Setenv、Clearenv只会影响程序当前运行环境中的环境变量。并不会对程序外的系统环境变量产生影响。所以当段代码运行结束时,系统的环境变量并不会发生改变。)

import "os"
import "strings"
import "fmt"

func main(){
	os.Setenv("ZZZ","abc")
	fmt.Println("ZZZ:",os.Getenv("ZZZ"))
	fmt.Println("XXX:",os.Getenv("XXX"))
	os.Unsetenv("ZZZ")
	fmt.Println("ZZZ:",os.Getenv("ZZZ"))
	for _,e := range os.Environ(){
		fmt.Println(e)
		pair := strings.Split(e,"=")
		fmt.Println(pair[0])
	}
}


运行结果:

ZZZ: abc
XXX: 
ZZZ: 
XDG_VTNR=8
XDG_VTNR
LC_PAPER=zh_CN.UTF-8
LC_PAPER
LC_ADDRESS=zh_CN.UTF-8
LC_ADDRESS


29.执行过程

import "syscall"
import "os"
import "os/exec"

func main(){
	ls()
	gorun()
}

func gorun(){
	binary,lookErr := exec.LookPath("go")
	if lookErr != nil{
		panic(lookErr)
	}
	args := []string{"go","run","sort.go"}
	env := os.Environ()
	execErr := syscall.Exec(binary,args,env)
	if execErr != nil{
		panic(execErr)
	}
}

func ls(){
	binary,lookErr := exec.LookPath("ls")
	if lookErr != nil{
		panic(lookErr)
	}
	args := []string{"ls","-a","-l","-h"}
	env := os.Environ()
	execErr := syscall.Exec(binary,args,env)
	if execErr != nil{
		panic(execErr)
	}
}


运行结果:

1.ls()
total 5.5M
drwxrwxr-x 2 tom tom  4.0K 12月 26 09:55 .
drwxrwxr-x 3 tom tom  4.0K 11月  9 12:50 ..
-rw-rw-r-- 1 tom tom   380 12月 11 15:05 atomic-counters.go
-rw-rw-r-- 1 tom tom   432 12月 21 11:59 base64-encoding.go
-rw-rw-r-- 1 tom tom  1.5K 11月 23 10:26 chan.go
-rw-rw-r-- 1 tom tom   117 12月 14 09:35 sort.go
2.gorun()
[8 11 12 52]


30.Signal信号
(https://www.jianshu.com/p/ae72ad58ecb6)
(该函数会将进程收到的系统Signal转发给channel c。转发哪些信号由该函数的可变参数决定,如果你没有传入sig参数,那么Notify会将系统收到的所有信号转发给c。如果你像下面这样调用Notify:

signal.Notify(c, syscall.SIGINT, syscall.SIGUSR1, syscall.SIGUSR2)

则Go只会关注你传入的Signal类型,其他Signal将会按照默认方式处理,大多都是进程退出。因此你需要在Notify中传入你要关注和处理的Signal类型,也就是拦截它们,提供自定义处理函数来改变它们的行为。)

import "fmt"
import "os"
import "os/signal"
import "syscall"

func main(){
	signalfun()
}

func signalfun(){
	sigs := make(chan os.Signal,1)
	done := make(chan bool,1)
	signal.Notify(sigs,syscall.SIGINT,syscall.SIGTERM)
	go func(){
		sig := <-sigs
		fmt.Println()
		fmt.Println("sig:",sig)
		done <- true
	}()
	fmt.Println("awaiting signal")
	<-done
	fmt.Println("exiting")
}


运行结果:

awaiting signal
^C
sig: interrupt
exiting


31.退出程序

import "fmt"
import "os"

func main(){
	defer fmt.Println("exit !!!")
	os.Exit(1)
}


运行结果:

exit status 1


学习网站:点击打开链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值