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())
}
运行结果:
12
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 1worker 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: 2117611.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: 92963writeOps: 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 90960writeNum 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()
}
运行结果:
creatingwriting
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 UTC18.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.0001604361513737102
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])
}
运行结果:
schemeuser: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 sha13de76d4897cfdfd9a44c66d124640a0d943ed592
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))
}
运行结果:
cc9983a1d0f02dc9281924ccd6ecf6cebfee047722.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: abcXXX:
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
学习网站:点击打开链接