一:文件操作
1.1:打开和关闭文件,读内容
func main() { //打开文件 openFileObj, err := os.Open("text.txt") if err!=nil{ fmt.Println("open file failed") return } defer openFileObj.Close()//关闭文件 }
1.2:打开文件读内容
1.2.1:read方法读文件
func readFromFile() { //读文件 readFileObj, err := os.Open("text.txt") if err!=nil{ fmt.Println("open file failed") return } defer readFileObj.Close()//关闭文件 //读文件 //var tmp=make([]byte,128)//指定读的长度 //openFileObj.Read(tmp) //上面两句也等于下面的写法 var tmp [128]byte for { n, err := readFileObj.Read(tmp[:]) if err==io.EOF{ fmt.Println("读完了") return } if err !=nil{ fmt.Println("read file failed",err)//EOF是end of file,读到文件末尾了 return } fmt.Printf("读了%d个字节 ",n) fmt.Println(string(tmp[:n]))//转换为字符串 if n<128 {//读128个字节 return } } }
1.2.2:bufio读文件,一行一行读写
func readFromFileBufio() { readFileObj, err := os.Open("text.txt") if err!=nil{ fmt.Println("open file failed") return } defer readFileObj.Close()//关闭文件 newReader := bufio.NewReader(readFileObj)//创建一个从文件中读取内容的对象 for {//使用for循环读 line, err := newReader.ReadString(' ') //注意是字符 if err == io.EOF { if len(line) != 0 { fmt.Println(line) } fmt.Println("文件读完了") break } if err != nil { fmt.Println("readFromFileByBufio failed, err:", err) return } fmt.Print(line) } }
1.2.3:ioutil读取整个文件
func readFileByIoutil() { ret, err := ioutil.ReadFile("text.txt")//直接就打开文件 if err!=nil { fmt.Printf("read file failed,err:%v",err) return } fmt.Println(string(ret))//转换为字符串 }
1.3:写文件
写文件的方式:
1.3.1:write和writestring写文件
func writeFile() { //打开文件,如果没有这个文件就会创建一个 fileObj, err := os.OpenFile("text.txt", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) //文件,写的方式,八进制数 if err != nil { fmt.Printf("open file failed,err:%v", err) return } fileObj.Write([]byte("Write 写的是字节 ")) fileObj.WriteString("WriteString写的是字符串") fileObj.Close() //关闭文件,可以使用defer,也可以直接关闭 }
1.3.2:bufio.NewWriter
func writeFileByBufio() { fileObj, err := os.OpenFile("t3.txt", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) //文件,写的方式,八进制数 if err != nil { fmt.Println("open file failed", err) return } defer fileObj.Close()//要用defer才能够写进去 writer := bufio.NewWriter(fileObj) for i := 0; i < 10; i++ { writer.WriteString("沙河 ") //将数据先写入缓存 } writer.Flush() //将缓存中的内容写入文件 }
1.3.3:ioutil.WriteFile
func writeFileByIoutil() { str := "writeFileIoutil" err := ioutil.WriteFile("t1.txt", []byte(str), 0666) if err != nil { fmt.Printf("open file failed,err:%v", err) return } }
二:strconv标准介绍
//从字符串中解析为整形的数据 str1 := "1000" //必须声明是字符串类型的,否则会报错 parseInt, err := strconv.ParseInt(str1, 10, 64) //转为10进制64位的 if err != nil { fmt.Println("parseInt failed,err:", err) } fmt.Printf("%#v", parseInt) //把数字转换为字符串 str2:= int32(97) ret1 := fmt.Sprintf("%d", str2) fmt.Printf("%v",ret1) //ret1:=string(str2) //go语言中是不能用string转换为字符串的 //字符串转换位数字 ret2, _ := strconv.Atoi(str1) fmt.Println(ret2) //数字转换位字符串 i:=97 ret3 := strconv.Itoa(i) fmt.Printf("%v",ret3) //从字符串中解析出布尔值 boolStr:="true" boolValue, _ := strconv.ParseBool(boolStr) fmt.Printf("%#v",boolValue) //从字符串中解析出浮点数 floatStr:="1.23" floatValue, err := strconv.ParseFloat(floatStr,64)//转换为64的float fmt.Printf("%#v",floatValue)
三:并发编程
Go语言的并发通过goroutine实现。goroutine类似于线程,属于用户态的线程,我们可以根据需要创建成千上万个goroutine并发工作。goroutine是由Go语言的运行时(runtime)调度完成,而线程是由操作系统调度完成。
Go语言还提供channel在多个goroutine间进行通信。goroutine和channel是 Go 语言秉承的 CSP(Communicating Sequential Process)并发模式的重要实现基础。
goroutine什么时候结束:goroutine对应的函数结束了,goroutine就结束了,main函数执行完了,由main函数创建的那些goroutine都结束了
3.1:使用goroutine
func main() { for i:=0; i<10;i++ { go hello(i)//函数前面加一个go是实现goroutine,开始一个单独的goroutine去执行hello函数 } fmt.Println("main")//此时只会输出main,本来是按顺序执行的,但是加了一个go之后会后执行,打印mian,打印完之后就结束了 //main都结束了,其他的也就结束了,要打印hello的话,此时要开启一个sleep time.Sleep(time.Second)//括号里面不能直接写1,写1的话是纳秒,会非常的快 } func hello(i int) { fmt.Println("使用goroutine") } //改成匿名函数 func main() { for i:=0; i<10;i++ { go func(i int) { fmt.Println(i) }(i) } fmt.Println("main") time.Sleep(time.Second) }
3.1.2:使用了sync.WaitGroup
来实现goroutine的同步
var wg sync.WaitGroup func main() { for i := 0; i < 10; i++ { wg.Add(1) // 启动一个goroutine就登记+1 go f1(i) } wg.Wait()// 等待所有登记的goroutine都结束 } func f1(i int) { defer wg.Done() //也可以这样子写 time.Sleep(time.Second * time.Duration(rand.Intn(10))) fmt.Println(i) //wg.Done() // goroutine结束就登记-1 }
3.1.3:math/rand随机数
func randNum() { rand.Seed(time.Now().UnixNano()) //因为每次执行,产生的随机数都是一样,所以加一个seed种子,time.Now().UnixNano()这个数一个int64的数数 for i := 0; i < 10; i++ { ret1 := rand.Int() ret2 := rand.Intn(10) //产生一个包括0,不包括10的随机数 fmt.Println(ret1, ret2) fmt.Println(0-ret1, 0-ret2)//用0减去这个数就是负数 } }
生成随机种子
//这两种是相等的 func main() { source := rand.NewSource(time.Now().UnixNano()) // 使用当前的纳秒生成一个随机源,也就是随机种子 ran := rand.New(source) // 生成一个rand fmt.Println(ran.Int()) // 获取随机数 } //func main() { // // 直接调用rand的方法生成伪随机int值 rand.Seed(time.Now().Unix()) // 设置种子,我们以当前时间的秒;当然也可以用毫秒,微秒等 fmt.Println(rand.Int()) fmt.Println(rand.Int31()) fmt.Println(rand.Intn(5)) }
3.1.4:goroutine调度模型GMP
var wg sync.WaitGroup func main() { runtime.GOMAXPROCS(1)//设置当前程序并发时占用的cpu数,默认是cpu的逻辑核心数,默认跑满cpu //runtime.NumCPU()//打印cpu的线程数 wg.Add(1) go f1() go f2() wg.Wait() } func f1() { defer wg.Done() for i:=0; i<10;i++{ fmt.Printf("A:%d ",i) }
3.2:channel
3.4:error错误
第一种:通过errors包去订制erro
error := errors.New("hello,error")//使用errors必须import "errors"包 if error != nil { fmt.Print(error) }
第二种:通过fmt.Errorf()去订制
err := fmt.Errorf("hello error") if err != nil { fmt.Print(err) }
第三种:就是通过自定义的MyError块去订制了
func main() { err := MyError{ errors.New("hello error"), } fmt.Println(err.Error()) } type MyError struct { err error } //订制Error() func (e MyError) Error() string { return e.err.Error() }