2019年1月

去网上查了一圈资料后,还是觉的os好用。

权限表

常量名权限
os.O_RDONLY只读
os.O_WRONLY只写
os.O_RDWR读写
os.O_APPEND追加
os.O_CREATE不存在时创建文件
os.O_TRUNC打开时截断文件

写文件

package main
import ("fmt"
        "os")
func checkerr(err error){
        if err != nil{
                fmt.Println(err)
                os.Exit(1)
        }
}
func main(){
        f,err := os.OpenFile("test.txt",os.O_RDWR|os.O_APPEND|os.O_CREATE,0644) //注意文件权限
        checkerr(err)
        defer f.Close()
        data := []byte("-1s -1s -1s\n") //转字节
        bytesw,err := f.Write(data) //写操作
        checkerr(err)
        fmt.Println("bytes:",bytesw)
}

读文件

package main
import ("fmt"
        "os")
func checkerr(err error){
        if err != nil{
                fmt.Println(err)
                os.Exit(1)
        }
}
func main(){
        f,err := os.Open("test.txt") //使用这种方式为只读
        //f,err := os.OpenFile("test.txt",os.O_RDONLY,0644)
        checkerr(err)
        defer f.Close()
        b := make([]byte,6) //读取6个字节,如果要读取全部,要用ioutil.ReadAll(fileObj)
        br,err := f.Read(b)
        checkerr(err)
        fmt.Println("bytes:",br)
        fmt.Println("data:",b)
        fmt.Println("str:",string(b))
}


从网上查到有Go中有两个包可以读写文件,一个是os包,另一个是ioutil包。
我主要用的是ioutil包,用起来比较简单,当然os也是有他的优势的。

读取文件

package main
import ("fmt"
        "reflect"
        "io/ioutil")
func main(){
        data,err := ioutil.ReadFile("test.txt")
        if err != nil{
                fmt.Println(err)
        }
        fmt.Println("Type:",reflect.TypeOf(data))
        fmt.Println("Data",string(data))
}
//output:
Type: []uint8
Data China Mogic Association
Founded in 1926, near the Huangpu river.
//可以看到,读出的是uint8类型的切片

写文件

这会覆盖文件!

package main
import "io/ioutil"
func checkrerr(err error){
        if err != nil{
                panic(err)
        }
}
func main(){
        data := []byte("+1s +1s +1s") //转字节
        err := ioutil.WriteFile("test.txt",data,0644)//文件掩码:-rw-r--r--
        checkrerr(err)
}

ERROR

概念

除了panicrecover之外,Go中还有一个内置的错误接口类型,任何类型只要实现Error() string方法,都可以传递error接口 类型变量,Go语言处理错误的方式是将error作为函数最后一个返回值,在调用函数时,通过检查其返回的error值是否为nil来进 行错误处理。

type error interface{ //接口类型
    Error() string
}

Go语言提供了两个函数返回实现了error接口的具体类型实例,一般的错误可以使这两个函数进行封装,当然,遇到复杂的错误也可以 自定义错误类型,只要实现error接口即可:

func New(text string) error{
    return &errorString{text}
}

最佳实践

  1. 在多个返回值的函数中,error一般作为最后一个返回值
  2. 如果一个函数返回error类型的变量,则先判断是否为nil
  3. defer语句应该放到err判断后面,不然可能产生panic
  4. 在错误逐层向上传递的过程中,错误信息应该不断的丰富与完善,而不是简单的抛出下层调用的错误,便于分析错误

33_error_0.PNG

其他要说的

Golang全面深入系列之 Error:https://studygolang.com/articles/12625
Go 语言如何实现error的优雅处理:https://blog.csdn.net/baogang409/article/details/72604333

阶段性总结

学了有一段时间了,也写了一些Go,感觉执行速度挺快的,毕竟不像Python这种解释性语言。部分语法与Python也很相像,从Python转到Go也不觉的陌生,学Go主要是写网络方面的程序,看网上的评价说Go对于网络编程性能还不错,要不然会有ngrok这种内网穿透的东东出 现。最后,路还长着,一次只学一点,细嚼慢咽的学。

搞得这个MicroPython啊,亦可赛艇。
经过上一篇文章,已经配置好了WiFi连接和Webrepl,下面我们来尝试与ESP8266来通信,在GPIO2上我接入了一个DS18x20温度传感器,通过访问ESP8266的8267端口,来获得ESP8266上传感器的数值。

main.py:
(在ESP8266上的socket库叫usocket,json库叫ujson)

 from ds18020 import DS18020
 import usocket
 import ujson
 import esp
 host = '0.0.0.0'
 port = 8267

 ds = DS18020(2)
 ds_addr = ds.getaddr()

 s = usocket.socket()
 s.bind((host,port))
 s.listen(6)
 while True:
     client,addr = s.accept()
     print('Client IP:',addr[0])
     info = {}
     info['flash_size'] = str(esp.flash_size())
     info['flash_free'] = str(esp.freemem())
     info['flash_id'] = str(esp.flash_id())
     info['ds18x20_temp'] = str(ds.gettemp(ds_addr[0]))
     print(info)
     client.send(ujson.dumps(info))
     info = {}
     client.close()

ds18020.py
(很惭愧,只做了一点的微小工作)

 import onewire
 import ds18x20
 import time
 from machine import Pin
 class DS18020:
     def __init__(self,pin):
         self.pin = Pin(pin)
     def getaddr(self):
         ow = onewire.OneWire(self.pin)
         self.ds = ds18x20.DS18X20(ow)
         roms = self.ds.scan()
         return roms
     def gettemp(self,addr):
         self.ds.convert_temp()
         time.sleep_ms(450)
         return self.ds.read_temp(addr)

效果:
31_0.PNG
今天还是挺冷的。