zoukankan      html  css  js  c++  java
  • go语言基本语法

    Go语言

    一、特点

    1、函数式编程   闭包

    2、工程化   资源管理,错误处理,测试文档,

    3、并发编程   goroutine和channel  调度器。

    4、接口编程, interface

    5、全新的静态类型开发语言

    6、更丰富的内置类型slice

    7、错误处理:
    defer, panic和recover

    二、语法

    Package声明:表示go代码所属的包。建立一个名字为main的包,在该包中包含一个叫做main()的函数。无参,也没有定义返回值。

    声明以后是import语句,引入需要的模块。

    需要使println()函数所以引入的是fmt

    函数定义使用func开头。

    所有Go函数(包括在对象编程中会提到的类型成员函数)以关键字func开头。一个常规的 函数定义包含以下部分: func 函数名(参数列表)(返回值列表) { // 函数体 } 对应的一个实例如下: func Compute(value1 int, value2 float64)(result float64, err error) { // 函数体 } Go支持多个返回值。以上的示例函数Compute()返回了两个值,一个叫result,另一个是 err。并不是所有返回值都必须赋值。在函数返回时没有被明确赋值的返回值都会被设置为默认 值,比如result会被设为0.0,err会被设为nil。

    三、定义变量

    package main

    import "fmt"

    var(
       a=3
       b=4
       c=2
       d=true
    )
    func variableZeroValue(){
       var a int
       var s string
       fmt.Printf("%d %q ", a, s)

    }
    func  variableInitialValue()  {
       var a, b int = 3, 4
       var s string = "abc"
      
    fmt.Println(a, b, s)
    }
    func variableDecouments(){
       var a, b, c, d = 1, 3, true, "def"
      
    fmt.Println(a,b,c,d)
    }
    func  variableShorters()  {
       a, b, c ,d := true, 0, 3, 5
       fmt.Println(a, b, c, d)
    }

    func main()  {
       fmt.Println("hello world")
       variableZeroValue()
       variableInitialValue()
       variableDecouments()
       variableShorters()
       fmt.Println(a, b, c, d)
    }

    := 只能在函数内使用

    四、内建变量类型

    1、bool,string

    2、(u)int无符号整数,不加u是有符号整数。

    Int32,int16,int8,int64,uintptr指针

    3、byets,rune字符型

    4、浮点型float32,float64,complex64, complex128负数

    cmplx.Pow(math.E, 1i * math.Pi)+1

    5、类型转换是强制的

    func euler(){

       fmt.Println(cmplx.Pow(math.E, 1i * math.Pi)+1)
       c := 3 + 4i
       fmt.Println(cmplx.Abs(c))
    }

    五、常量

    1、普通的定义

    func consts(){
       const filename = "abc"
       const a
    , b = 3, 4
       fmt.Println(filename, a, b)
    }

    定义在函数内和函数外是一样的,都可以定义

    2、枚举定义

    普通类型就是自己定义

    Iota是自增类型

    func enums(){
       const (cpp  = iota
       python
       golang
       javascript
    )
       fmt.Println(cpp, python, golang, javascript)
    }

    六、条件语句

    1、if

    package main

    import (
       "fmt"
       "io/ioutil"
    )

    //func main()  {
    // const filename  = "abc.txt"
    // contents, err := ioutil.ReadFile(filename)
    // if err != nil{
    //    fmt.Println(err)
    // }else {
    //    fmt.Println("%s ", contents)
    // }
    //}
    func main()  {
       const filename  = "abc.txt"
       if
    contents, err := ioutil.ReadFile(filename); err == nil{
          fmt.Println(string(contents))
       }else {
          fmt.Println("cannot print file contents", err)
         
       }

    }

    直接父类加

    2、switch

    func grade(source int) string{
       g := ""
       switch 
    {
       case source < 0 || source > 100:
          panic(fmt.Sprintf("wrong score: %d", source))
       case source < 60:
          g = "f"
       case
    source < 80:
          g = "c"
       case
    source < 900:
          g = "b"
       case
    source <= 100:
          g = "a"
      
    }
       return g
    }

    panic异常捕获语句

    switch不需要break,自动有的break

    3、for循环

    func sums(){
       sum := 0
       for i := 1; i <=100; i++{
          sum += i
       }
       fmt.Println(sum)
    }

    for 什么不加的话就是死循环,不用的是while

    七、函数

    func div(a, b int)(q, r int){
       return a / b, a % b
    }

    函数名(参数,参数类型)(返回值,返回值类型)

    可变参数只有一个就是..int

    函数作为参数

    八、指针

    只有值传递一种方式。

    *a ,*b,指针

    &a,&b取地址

    第一种实现

    func swap(a, b *int)  {
       *a, *b = *b, *a
    }
    a, b := 2, 4
    swap(&a, &b)
    fmt.Println(a, b)

    第二种实现方式:

    func swaps(a, b int) (int, int) {
       return b, a
    }

    九、数组

    package main

    import "fmt"

    func
    main(){
       var arr1 [5] int
       arr2 := [3]int{1, 3 ,5}
       arr3 := [...]int{2, 4, 6, 8, 10}
       var grid[4][5] int
       fmt.Println(arr1, arr2, arr3, grid)
       for i, value := range arr3{
          fmt.Println(i, value)
       }
    }

    定义了必须使用,要不然就使用_忽略变量

    利用range。

    意义明显。

    数组是值类型,值类型会进行相应的拷贝文件

    package main

    import "fmt"
    func
    printarray(arr [5]int){
       for i, v := range arr{
          fmt.Println(i, v)
       }

    }
    func main(){
       var arr1 [5] int
       arr2 := [3]int{1, 3 ,5}
       arr3 := [...]int{2, 4, 6, 8, 10}
       var grid[4][5] int
       fmt.Println(arr1, arr2, arr3, grid)
       //for i, value := range arr3{
          //fmt.Println(i, value)
       //}
      
    printarray(arr3)
       }

    var arr[5] int 指定的是数组的长度和值得类型

    数组作为函数的参数穿进去的时候就会拷贝数组

    一般不会直接使用数组

    十、切片slice

    package main

    import "fmt"

    func
    main()  {
       arr := [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
       s := arr[2:6]
       s1 := s[3:5]
       fmt.Println(s)
       fmt.Println(s1)
    }

    s1 因为知道其索引脚标,所以能够取出所在的值。因为其知道s的值,向后拓展只要不是超过s的长度即可

    可以进行append,进行写入相关数据。

    十一、Map

    Map[k]v,map[k1]map[k2]v

    创建make ,map    m2 := make(map[string]int)      m := map[string]string

    遍历

    查找值

    删除

    Map的key:map使用的是哈希表,必须可以比较相等。

    除了slice,map,function的内建类型都可以作为key,

    Struct类型不包括上述字段,也可以作为key

    package main

    import "fmt"

    func
    main()  {
       m := map[string]string{    //no1
         
    "name":"mouse",
          "course":"golang",
          "site":"imocc",
          "quality":"notbad",
       }
       m2 := make(map[string]int)   // no2   == empty map
      
    var m3 map[string]int      //no3   == nil
      
    fmt.Println(m, m2, m3)
       for k := range m{       //遍历
         
    fmt.Println(k)

       }
       for k,v := range m{     //遍历
         
    fmt.Println(k,v)
       }
       courname := m["course"]     //索引查找,通过k查找v。如果不存在则是显示flase
      
    fmt.Println(courname)
       name, ok := m["course"]
       fmt.Println(name, ok)
       delete(m, "name")     //删除元素
      
    fmt.Println(m)
       }

    十二、字符串

    package main


    func lengthSubstr(s string) int{
       last0curred := make(map[byte]int)
       start := 0
       maxlength := 0
       for i, ch := range []byte(s){
          if last0curred[ch] < start{
             start = last0curred[ch] + 1

          }
          if i - start + 1 > maxlength{
             maxlength = i - start +1
          }
          last0curred[ch] = i
       }
       return maxlength
    }

    func main() {
       lengthSubstr()
    }
     
    
    
     
    Strings.map等操作
     
    
    
     
     

    十三、类

    只是支持封装,不支持继承和多态。

    没有class 只有struct

    Type point struct {i,j,int}

    package main

    import "fmt"

    type
    treeNode struct {
       value int
       left, right * treeNode
    }

    func createNode(value int) *treeNode{
       return &treeNode{value:value}
    }

    func main()  {
       var root treeNode
       root = treeNode{value:3}
       root.left = &treeNode{
       }
       root.right = &treeNode{5, nil, nil}
       root.right.left = new(treeNode)
       root.left.right = createNode(2)

       nodes := []treeNode{
          {value:3},
          {},
          {6, nil, &root},
       }
       fmt.Println(nodes)
    }

    结构创建在堆上还是栈上呢。

    利用指针接收

    十四、封装

    名字一般使用camelcase

    首字母大写public

    首字母小写 private

    十五、扩展已有类型

    包:每个目录里面一个包

    Main包包含可执行入口

    为结构定义的方法必须放在同一个包内

    可以是不同的文件。

    Go语言没有继承:

    如何扩充已有类型和别人的类型。

    (1)定义别名

    package queue

    import "fmt"

    type
    Queue []int

    func (q *Queue) Push(v int){
       *q = append(*q, v)
    }

    func (q *Queue) Pop() int {
       head := (*q)[0]
       *q = (*q)[1:]
       return head
    }

    func main(){
       q := queue.Queue{1}

       q.Push(2)
       q.Push(3)
       fmt.Println(q.Pop())
       fmt.Println(q.Pop())
       fmt.Println(q.IsEmpty())
       fmt.Println(q.Pop())
       fmt.Println(q.IsEmpty())
    }

    (2)使用组合

    十六、Gopath环境

    不用的包不能导入,否则就会报错的

    十七、接口

    1、duck typing

    2、Go语言中的duck typing

    假的retriever
    package mock

    type Retriever struct {      //定义retriever类
       Contents string
    }

    func (r Retriever) Get(url string) string{
       return r.Contents
    }

    really接口

    package real

    import (
       "net/http"
       "net/http/httputil"
       "time"
    )

    type Retriever struct {
       UserAgent string
       TimeOut time.Duration
    }
    func (r Retriever) Get(url string) string{
       resp, err := http.Get(url)
       if err != nil{
          panic(err)
       }
       result, err := httputil.DumpResponse(resp, true)
       resp.Body.Close()

       if err != nil{
          panic(err)
       }
       return string(result)
       }
    package main

    import ("fmt"
       "go-projects/retriever/mock"
    )

    type Retriever interface {     //定义了接口
       Get(url string) string     //定义了方法而已
    }

    func download(r Retriever) string {  //接口作为参数传入,然后调用定义 的Get函数
       return r.Get("www.123.com")
    }
    func main()  {
       var r Retriever
       r = mock.Retriever{"this is imock"}
       fmt.Println(download(r))

    }

    3、接口定义:

    接口是隐士的,只是实现里面的方法啊而已

    Interface  里面有两个东西一个是值,一个是类型,真实的值copyde,也可以是指针的。

    4、接口的组合:

    type RetrieverPoster interface {
       Retriever
       Poster
    }

    是许多小接口的组合,把许多小接口放在一起

    传值的时候传retriever,都是具备的,r只是具备单一的

    5、go语言标准的接口

    Stringer:

    Writer

    十八、函数式编程

    函数式编程  

    函数指针   高阶函数,函数到闭包

    正统函数式编程:

    1、不可变性:不能有状态,只有常量和函数

    2、函数只能有一个参数。

    package main

    import "fmt"

    func
    adder() func(int) int{
       sum := 0
       return func(v int) int {
          sum += v
          return sum
       }
       }

    func main() {
       a := adder()
       for i := 0; i < 10; i++{
          fmt.Println(a(i))
       }
    }

    正统式函数编程:

    type iAdder func(int)(int, iAdder) 

    func adder2(base int) iAdder {
       return func(v int) (int, iAdder) {
          return base + v, adder2(base + v)
       }
    }
    func main() {
    a1 := adder2(0)
    for i := 0; i < 10; i++{
       var s int
       s, a1 = a1(i)
       fmt.Printf("0 + 1 + ... + %d = %d ", i, s)
    }

    }

    Go语言中也有匿名函数,没有名字的。

    十九、异常处理

    1、defer调用

    package main

    import "fmt"

    func
    tryDefer()  {
       defer fmt.Println(1)
       fmt.Println(2)
       fmt.Println(3)

    }
    func main() {
       tryDefer()
    }

    添加defer之后不受return 和panic的影响

    Go语言是因为栈的,先进后出的。

    实现斐波那契数列,必须注意的是函数名字的大写

    package fib

    func Fibonacci() func() int{
       a, b := 0, 1
       return func() int {
          a, b = b, a + b
          return a
       }
    }
    package main

    import (
       "bufio"
       "fmt"
       "os"
       "go-projects/functional/fib"
    )

    func tryDefer()  {
       defer fmt.Println(1)
       fmt.Println(2)
       fmt.Println(3)

    }
    func writeFile(filename string){
       file, err := os.Create(filename)
       if err != nil{
          panic(err)
       }
       defer file.Close()

       writer := bufio.NewWriter(file)
       defer writer.Flush()

       f := fib.Fibonacci()
       for i := 0; i<20; i ++{
          fmt.Fprintln(writer, f())
       }
    }
    func main() {
       tryDefer()
       writeFile("abc.txt")
    }

    何时调用 defer  

    在open/close

    Lock/unlock

    Printhead/printfooter

    错误处理的概念:

    func writeFile(filename string){
       //file, err := os.Create(filename)
      
    file, err := os.OpenFile(filename, os.O_EXCL|os.O_CREATE, 0666)
       if err != nil{
          if pathError, ok := err.(*os.PathError); !ok{
             panic(err)
          }else {
             fmt.Println("%s, %s, %s ",
                pathError.Op,
                pathError.Path,
                pathError.Err)
          }
          return
         
    }
       defer file.Close()

       writer := bufio.NewWriter(file)
       defer writer.Flush()

       f := fib.Fibonacci()
       for i := 0; i<20; i ++{
          fmt.Fprintln(writer, f())
       }
    }
    func main() {
       tryDefer()
       writeFile("abc.txt")
    }

    自己创建error的类型

    err = errors.New("this is a custom error")

    统一的错误处理逻辑:

    2、服务器内部的错误资源处理流程,统一的处理

    package main

    import (
       "io/ioutil"
       "net/http"
       "os"
    )

    func main() {
       http.HandleFunc("/list/",
          func(writer http.ResponseWriter, request *http.Request) {
             path := request.URL.Path[len("/list/"):]
             file, err := os.Open(path)
             if err != nil{
                panic(err)
             }
             defer file.Close()
             all, err := ioutil.ReadAll(file)
             if err != nil{
                panic(err)
             }
             writer.Write(all)
             })
       err := http.ListenAndServe(":888", nil)
       if err != nil{
          panic(err)
       }
    }

    一个简单的网页 程序。

    直接给前端页面返回的是程序的错误代码

    http.Error(writer,
       err.Error(),
    http.StatusInternalServerError)

    os.isempty   如果是空的话

    使用主函数处理函数内部逻辑,外部进行一场的捕获即处理例如Python的装饰器的形式

    func main() {
       http.HandleFunc("/list/",
          errWrapper(filelisting.Handlefilelist))

       err := http.ListenAndServe(":8888", nil)
       if err != nil{
          panic(err)
       }
    }

    panic和recover的区别:

    1、panic

    停止当前函数执行

    一直向上返回,执行每一层的defer

    如果没有recover,程序退出。

    2、recover

    仅在defer调用中使用

    获取panic的值

    如果无法获取,可重新panic

    工作流程如下:

    panic(errors.New("this is an error"))自己可以创建的异常的值和类型。
     
    package main

    import (
       "errors"
       "fmt"
    )

    func tryRecover()  {
       defer func() {
          r := recover()
          if err, ok := r.(error); ok{
             fmt.Println("Error occurred", err)
          }else {
             panic(r)
          }
       }()
       panic(errors.New("this is an error"))
    }
     
     
    尽量少用panic。
     
    意料之内的使用error, 文件打不开
     
    意料之外的使用panic, 数组超届
     
    错误综合处理方法:
    
    
     
     
  • 相关阅读:
    ArcGIS学习记录—union、merge及append的区别
    ArcGIS学习记录—属性表的编辑与修改
    ASP.NET应用程序和ASP.NET网站所共有的文件: App_Browsers 等
    C# 文件夹操作
    远程重启服务器
    SQL省市区三级表结构
    c#提出中文首字母
    javascript遍历Json对象个数
    原生javascript添加引用js文件
    简单的div蒙层
  • 原文地址:https://www.cnblogs.com/wangchunli-blogs/p/9951245.html
Copyright © 2011-2022 走看看