首页 > 学院 > 开发设计 > 正文

golang的基本语法

2019-11-06 06:32:19
字体:
来源:转载
供稿:网友

最近又打算玩玩golang,打算把工作中的爬虫从脚本语言迁移到golang,读了两本golang的书,对立面的语法做了一个简单的整理。

编程语言的选择

0 业务的要求1 性能2 表达能力3 是否容易上手4 坑和维护

变量

变量的声明var xx type 或者 var (xx type xxx type)

初始化

var v1 i = 10; var v2 = 10; v3 := 10

交换值

i,j = j,i

多个值

_,a = 11,34

常量

const pi float32 = 1.2const zero = 11const( a1 int32 = 11; a2 = 11;)const a2 = 1 << 2

预定义常量

const( c0=iota;c1=iota;c2=iota;)//iota 值自动增加const (a = 1 << iota; b ; c;)

枚举

const( day1=iota;day2;day3;day4;)

类型

bool var b1 bool = true; b2 := (1 == 2);int8,byte int16 int unit unitptr int32 unit32 int64 unit64 int unit 整型是不同的,数值运算,比较运算,位运算float32 float64 var f1 float32 = 11.1; 不能直接比较大小,可以计算减法比较complex64 complex128 com1 := 3+12i; 实部real(com1); 虚部imag(com1)string str1 := "hi"; len(str1);str1[0]; 字符串的运算 加 x+y 长度 len(s) 取字符 s[i] 字符串的遍历 for k,v := range str{ fmt.PRintln(k,v); }rune字符类型 byte,uint8的别名,一个是rune 代表unicode字符 unicode/utf8包提供utf-8和unicode的转换指针 pointer数组 array [32]int;[2*N]struct{x,y int32};[3][5]int 长度 alen := len(arr) 遍历 下标遍历,range遍历, 数组是值类型,传递是拷贝切片 slice 创建切片 arr[a:b]; make([]int,len,cap); 遍历 小标遍历,range遍历 常用函数 len长度 cap容量 可以基于切片创建切片 新增元素 slice=append(slice,11) 内容复制 copy(slice1,slice2);字典 map 创建字典 make(map[string]int,len) 赋值 map1[key] = val1 查找字典 p,ok := map1[key1] 删除 delete(map1,"k1")通道 chan结构体 struct接口 interfaceerror

流程语句

选择 if,else 和else if if xxx{ }else{ } switch switch xx{ case 1: fallthrough case 2: default: } select循环 for for{} for a;b;c;{} break 跳出循环 continue 继续 range 循环跳转 HERE: goto HERE

init()函数main前调用

函数

func (t *R) funcname(a type,b type)(ret type, err error){ return a,nil}函数返回nil比较多调用 a:= funcname(a,b); a:= FTT.funcname(a,b); 不定参数 func funcname2(arg ...int){ funcname3(arg...) }任意参数 func funcname3(args ...interface{})匿名函数 func(x,y int)int{ return x+y } //调用匿名函数 func(x,y int)int{ print(x,y) }(1,2) 闭包: j :=3; func()(func()){ var i int = 1; return fun(){ fmt.Printf("i,j:%d,%d/n",i,j); } }()

获取数据的类型

xxx.(type)

nil

代表空

defer和panic 错误处理

error的定义type error interface{ Error() string}defer 延后处理 例如defer func(){}()

panic() 和recover()

panic()释放错误defer func(){ if r:= recover();r!=nil{ log.Printf("xxx"); }}()

import

相对路径 import "./xx"绝对路径 import "xx/xx"点导入 import . "math" 可以直接 sqrt()别名 import f fmt 可以f.printf(xxx)_操作 _"github.com/xxx" 引用包不是直接调用函数,而是使用了包里面的init方法

go的类型系统

基础类型 byte int bool float符合类型 数组,结构体,指针任意类型 interface{}值和引用语义面向对象接口go 里面有引用语义的 切片,map,channel,接口

结构

type A struct{ stat int}func ( a A) add(a1 int,b1 int ) int{ return a1+b1}初始化 a1 := new(A) a2 := &A{} a3 := &A{1} a4 := &A{stat:1}自建构造函数 func NewA(stat int){ return &A{stat} }匿名组合 type B struct{ A } type B struct{ *A }可见性 通过大小写控制

接口

type Read interface{ Reader(buf []byte)(n int,err error)}type FileReader struct{ int xx;}实现接口func (fr *FileReader)Reader(buf []byte)(n int,err error){ return 1,nil}接口的赋值 对象赋值给接口通过引用 file_reader := new(FileReader); var b Read = file_reader 将接口赋值给接口 只需要一个是另外一个的子集即可,反过来不成立 IA > IB IA = IB接口查询 检查是否实现了接口 if xx,ok := file_reader.(Read);ok{ }接口组合 type interface1 interface{ read()(n int,err error) } type interface2 interface{ write()(n int,err error) } type interface3 interface{ interface1 interface2 }

任意类型

interface{}

类型查询

switch v:= v1.(type){ case xx1: case xx2: case xx3:}

并发

通过go实现 main方法调用go的方式 1 主线程睡眠 2 使用管道等待 3 for或者select死循环管道的声明 ch := make(chan int)管道写入数据 ch <- value 管道数据写入变量 value := <-chselect go在语言级别支持select select{ case <-chan1://chan1读取数据执行下面 case chan2 <- 1: chan2读取成功 default:默认流程 }缓冲机制-自带线程池 c :=make(chan int,1023) for i:= range c{ printf("receiverd: ",i); }超时机制 1 定义一个chan运行,到时间写即可,可以使用select来实现 2 也可以 使用 time.After(5.time.Second)传递性 可以通过chan传递数据 type PipeData struct { value int handler func(int) int next chan int } func handle(queue chan *PipeData) { for data := range queue { data.next <- data.handler(data.value) } }单向管道 读写 var ch1 chan int 写 var ch2 chan<- float32 读 var ch2 <-chan int关闭管道 close(ch)多核化 cpu个数的管道Gosched让出时间片 同步 sync.Mutex sync.RWMutex 全局唯一操作 var once sync.Once once.Do(xxx)go并发相关函数: Goexit 退出去 Gosched 让出执行权限 NumCPU cpu核数量 NumGoroutine 执行和排队的携程数 GOMAXPROCES 核心数

反射

t := reflect.TypeOf(i) //得到类型的元数据,通过t我们能获取类型定义里面的所有元素v := reflect.ValueOf(i) //得到实际的值,通过v我们获取存储在里面的值,还可以去改变值转化为reflect对象之后我们就可以进行一些操作了,也就是将reflect对象转化成相应的值,例如tag := t.Elem().Field(0).Tag //获取定义在struct里面的标签name := v.Elem().Field(0).String() //获取存储在第一个字段里面的值

访问MySQL数据库

package mainimport ( _ "github.com/Go-SQL-Driver/MySQL" "database/sql" "fmt" //"time")func main() { db, err := sql.Open("mysql", "astaxie:astaxie@/test?charset=utf8") checkErr(err)//插入数据stmt, err := db.Prepare("INSERT userinfo SET username=?,departname=?,created=?") checkErr(err)res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09") checkErr(err)}

使用redis

package mainimport ( "github.com/astaxie/goredis" "fmt")func main() { var client goredis.Client client.Set("a", []byte("hello")) val, _ := client.Get("a") fmt.Println(string(val)) client.Del("a") //list操作 var client goredis.Client vals := []string{"a", "b", "c", "d", "e"} for _, v := range vals { client.Rpush("l", []byte(v)) } dbvals,_ := client.Lrange("l", 0, 4) for i, v := range dbvals { println(i,":",string(v)) } client.Del("l") }

操作xml

package mainimport ( "encoding/xml" "fmt" "io/ioutil" "os")type Recurlyservers struct { XMLName xml.Name `xml:"servers"` Version string `xml:"version,attr"` Svs []server `xml:"server"` Description string `xml:",innerxml"`}type server struct { XMLName xml.Name `xml:"server"` ServerName string `xml:"serverName"` ServerIP string `xml:"serverIP"`}func main() { file, err := os.Open("servers.xml") // For read access. if err != nil { fmt.Printf("error: %v", err) return } defer file.Close() data, err := ioutil.ReadAll(file) if err != nil { fmt.Printf("error: %v", err) return } v := Recurlyservers{} err = xml.Unmarshal(data, &v) if err != nil { fmt.Printf("error: %v", err) return } fmt.Println(v) }

正则表达式

func Match(pattern string, b []byte) (matched bool, error error)func MatchReader(pattern string, r io.RuneReader) (matched bool, error error) func MatchString(pattern string, s string) (matched bool, error error)解析正则 func Compile(expr string) (*Regexp, error) func CompilePOSIX(expr string) (*Regexp, error) func MustCompile(str string) *Regexp func MustCompilePOSIX(str string) *Regexp查找 func (re *Regexp) Find(b []byte) []byte func (re *Regexp) FindAll(b []byte, n int) [][]byte func (re *Regexp) FindAllIndex(b []byte, n int) [][]int func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int func (re *Regexp) FindIndex(b []byte) (loc []int) func (re *Regexp) FindSubmatch(b []byte) [][]byte func (re *Regexp) FindSubmatchIndex(b []byte) []int

模板处理

html/template"

文件处理

目录文件操作的大多数函数都是在os包里面,下面列举了几个目录操作的: func Mkdir(name string, perm FileMode) error创建名称为name的目录,权限设置是perm,例如0777 func MkdirAll(path string, perm FileMode) error根据path创建多级子目录,例如astaxie/test1/test2。 func Remove(name string) error删除名称为name的目录,当目录下有文件或者其他目录是会出错 func RemoveAll(path string) error根据path删除多级子目录,如果path是单个名称,那么该目录不删除。文件 func Create(name string) (file *File, err Error) 根据提供的文件名创建新的文件,返回一个文件对象,默认权限是0666的文件,返回的文件对象是可读写 func NewFile(fd uintptr, name string) *File 根据文件描述符创建相应的文件,返回一个文件对象打开 func Open(name string) (file *File, err Error) 该方法打开一个名称为name的文件,但是是只读方式,内部实现其实调用了OpenFile。 func OpenFile(name string, flag int, perm uint32) (file *File, err Error) 名字,方式,权限写func (file *File) Write(b []byte) (n int, err Error) 写入byte类型的信息到文件func (file *File) WriteAt(b []byte, off int64) (n int, err Error) 在指定位置开始写入byte类型的信息func (file *File) WriteString(s string) (ret int, err Error) 写入string信息到文件读 func (file *File) Read(b []byte) (n int, err Error) func (file *File) ReadAt(b []byte, off int64) (n int, err Error)

字符串处理

字符串操作func Contains(s, substr string) boolfunc Join(a []string, sep string) stringfunc Index(s, sep string) intfunc Replace(s, old, new string, n int) stringfunc Repeat(s string, count int) stringfunc Split(s, sep string) []stringfunc Trim(s string, cutset string) stringfunc Fields(s string) []string字符串转换 str := make([]byte, 0, 100) str = strconv.AppendInt(str, 4567, 10) str = strconv.AppendBool(str, false) str = strconv.AppendQuote(str, "abcdefg") str = strconv.AppendQuoteRune(str, '单') a := strconv.FormatBool(false) b := strconv.FormatFloat(123.23, 'g', 12, 64) c := strconv.FormatInt(1234, 10) d := strconv.FormatUint(12345, 10) e := strconv.Itoa(1023) a, err := strconv.ParseBool("false") if err != nil {fmt.Println(err) } b, err := strconv.ParseFloat("123.23", 64) if err != nil { fmt.Println(err) } c, err := strconv.ParseInt("1234", 10, 64) if err != nil { fmt.Println(err) } d, err := strconv.ParseUint("12345", 10, 64) if err != nil { fmt.Println(err) } e, err := strconv.Itoa("1023") if err != nil { fmt.Println(err) } fmt.Println(a, b, c, d, e) }

websocket

"code.google.com/p/go.net/websocket" 服务

gdb调试

日志系统

seelog

部署

daemon

性能监控

net/http/pprofruntime/pprof

常用的库

net包socket 库 Dial(net,addr string)(Conn,error) conn,err := net.Dial("tcp","127.0.0.1:8888") conn,err := net.Dial("udp","127.0.0.1:8888") conn,err := net.Dial("ip4:icmp","www.baidu.com") conn,err := net.Dial("ip4:1","10.113.1.103") 目前支持的协议: tcp tcp4 tcp6 udp upd4 udp6 ip ip4 ip6dial实际上是对函数的封装 func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err error) func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err error) func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error)func DialUnix(net string, laddr, raddr *UnixAddr) (c *UnixConn, err error)http库,net/http包 func (c *Client) Get(url string) (r *Response, err error) func (c *Client) Post(url string, bodyType string, body io.Reader) (r *Response, err error)func (c *Client) PostForm(url string, data url.Values) (r *Response, err error) func (c *Client) Head(url string) (r *Response, err error)func (c *Client) Do(req *Request) (resp *Response, err error)http服务端编程 http.Handle("/foo", fooHandler) http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path)) } ) log.Fatal(http.ListenAndServe(":8080", nil)) 或者是 s := &http.Server{ Addr:":8080", Handler:myHandler, ReadTimeout:10 * time.Second, ReadTimeout:10 * time.Second, MaxHeaderBytes: 1 << 20, } log.Fatal(s.ListenAndServe()) https有点不同 log.Fatal(http.ListenAndServeTLS(":10443", "cert.pem", "key.pem", nil)) RPC net/rpc直接支持 服务端 arith := new(Arith) rpc.Register(arith) rpc.HandleHTTP() l, e := net.Listen("tcp", ":1234") if e != nil { log.Fatal("listen error:", e) } go http.Serve(l, nil) 客户端 client, err := rpc.DialHTTP("tcp", serverAddress + ":1234") if err != nil { log.Fatal("dialing:", err) } args := &server.Args{7,8} var reply int err = client.Call("Arith.Multiply", args, &reply) if err != nil { log.Fatal("arith error:", err) } fmt.Printf("Arith: %d*%d=%d", args.A, args.B, reply) Gob Gob 是 Go 的一个序列化数据结构的编码解码工具 json处理 压缩一个数据,放到另外一个数据里面 func Marshal(v interface{}) ([]byte, error) func Unmarshal(data []byte, v interface{}) error �� JSON中的布��值将会��换为Go中的bool类型; �� 数值会被��换为Go中的float64类型; 字符����换后还是string类型; JSON数组会��换为[]interface{}类型; JSON对象会��换为map[string]interface{}类型; �� null值会��换为nil。 md5和sha1 package main import( "fmt" "crypto/sha1" "crypto/md5" ) Md5Inst:=md5.New() Md5Inst.Write([]byte(TestString)) Result:=Md5Inst.Sum([]byte("")) fmt.Printf("%x/n/n",Result) Sha1Inst:=sha1.New() Sha1Inst.Write([]byte(TestString)) Result=Sha1Inst.Sum([]byte("")) fmt.Printf("%x/n/n",Result)
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表