go基础知识学习

[toc]

最近没有继续部署elk系统和学习,是因为有项目进来了,自己需要学多一门语言go,学学吧,多学无害,但最怕学艺不精,最怕样样都懂点,样样都不深~

基础组成

  • 包声明
  • 引入包
  • 函数
  • 变量
  • 语句 & 表达式
  • 注释
package main

import "fmt"

func main() {
   /* 这是我的第一个简单的程序 */
   fmt.Println("Hello, World!")
}

每个Go应用程序都包含一个名为main的包,func main()时候程序开始执行的函数,如果有init()函数则会先执行该函数
注意:{不能单独

基础语法

  • 标记有关键字,标识符,常量,字符串,符合
  • go程序中,一行代表一个语句结束。不需要以分号结尾,这些由go编译器自动完成
  • 标识符用来命名变量、类型等程序实体,第一个字符必须是字母或者下划线不能是数字
  • 数据类型用于声明函数和变量,他的出现是为了把数据分成所需内存大小不同的数据,节省内存空间
  • 声明变量是这样写的var identifier type,例如:var xxx string = "XXX"
  • 变量声明:①指定变量类型,没有初始化,则变量默认为零值,零值就是系统默认设置的值。字符串的默认类型是空字符串"";②根据值自行判定变量类型,var d = true;③省略var,注意:=左侧如果没有声明新的变量,就会产生编译错误,var f sring = "X"可以写成f := "X"
var val int
val := 1 // 编译错误
val, val2 := 1, 2 //没有错,:=是一个声明语句
  • 因式分解关键字的写法一般用于声明全局变量
var(
    vname1 vtype1
    vname2 vtype2
)
  • 不带声明格式的只能在函数体中出现
  • 常见的如int、float、bool基本类型都是值类型,使用这些类型的变量直接指向在内存中的值,当用=复制的时候,实际上是在内存中将i的值进行了拷贝
  • 引用类型,跟c语音的差不多,有指针概念
  • 局部变量中声明了变量又没使用到,会报错 a declared and not used
  • 如果想交换两个变量的值,可以简单使用a, b = b, a,这两个变量的类型必须相同
  • 空白标识符_也被用于抛弃值,如值5在_, b = 5, 7中被抛弃。_实际上是一个只写变量,不能拿到它的值,go语言中你必须使用所有被声明的变量,但是有时候你并不需要使用从一个函数得到的所有返回值
  • 并行赋值,用于一个函数返回多个值时,可以用多个变量受值

常量

  • const 常量声明,也可以当做枚举使用。常量可以用函数计算表达式的值,函数萹蓄是内置函数,否则编译错误
const LENGTH = 10
const (
    Unknown = 0
    Female = 1
    Male = 2
)
  • iota,特殊常量,可以被编译器修改的常量。第一个iota等于0,每当iota在新的一行中被使用时,他的值都会自动加1,所以a=0,b=1,c=2可以简写如下形式
const (
    a = iota
    b
    c
)

package main

import "fmt"

func main() {
    const (
            a = iota   //0
            b          //1
            c          //2
            d = "ha"   //独立值,iota += 1
            e          //"ha"   iota += 1
            f = 100    //iota +=1
            g          //100  iota +=1
            h = iota   //7,恢复计数
            i          //8
    )
    fmt.Println(a,b,c,d,e,f,g,h,i)
}
运行结果0 1 2 ha ha 100 100 7 8

运算符

  • 算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符、其他运算符
  • 位运算符:&按位与运算符,|按位或运算符,^按位异或运算符,<<左移运算符(乘以2的n次方),>>右移运算符(除以2的n次方)
  • 其他运算符,&返回变量存储地址,*指针变量

条件语句

  • 特别的是select语句,类似switch,但是他是随机执行一个可运行的case,没有可运行的case,就会阻塞,直到有case可运行
  • go没有三目运算符,所以不支持?:形式的条件判断
  • switch不用break
  • type switch,来判断某个变量实际存储的变量类型
  • 使用 fallthrough 会强制执行后面的 case 语句,fallthrough 不会判断下一条 case 的表达式结果是否为 true

循环语句

  • 无特别之处

函数

  • 函数定义格式如下
func function_name( [parameter list] ) [return_types] {
   函数体
}
例子
func max(num1, num2 int) int {
   /* 声明局部变量 */
   var result int

   if (num1 > num2) {
      result = num1
   } else {
      result = num2
   }
   return result 
}

func max(num1, num2 int) (int, int) {
    return num1, num2
}
  • 函数参数类型有两种:值传递,引用传递
  • 函数定义后可以作为另一个函数的实际参数传入
  • 支持匿名函数,可作为闭包。匿名函数是一个“内联”语句或表达式。匿名函数的优越性在于可以直接使用函数内的变量,不必申明
package main

import "fmt"
func main() {
    add_func := add(1,2)
    fmt.Println(add_func())
    fmt.Println(add_func())
    fmt.Println(add_func())
}

// 闭包使用方法
func add(x1, x2 int) func()(int,int)  {
    i := 0
    return func() (int,int){
        i++
        return i,x1+x2
    }
}
结果:
1 3
2 3
3 3
package main
import "fmt"
func main() {
    add_func := add(1,2)
    fmt.Println(add_func(1,1))
    fmt.Println(add_func(0,0))
    fmt.Println(add_func(2,2))
} 
// 闭包使用方法
func add(x1, x2 int) func(x3 int,x4 int)(int,int,int)  {
    i := 0
    return func(x3 int,x4 int) (int,int,int){ 
       i++
       return i,x1+x2,x3+x4
    }
}
结果:
1 3 2
2 3 0
3 3 4

变量作用域

  • pointer的初始化默认值nil

数组

  • 无特别

指针

  • 取地址符&,放到一个变量前使用就会返回相应变量的内存地址
  • nil空指针,一个指针通常缩写为ptr

结构体

  • 结构体定义需要使用type和struct语句。struct语句定义一个新的数据类型
package main

import "fmt"

type Books struct {
   title string
   author string
   subject string
   book_id int
}


func main() {

    // 创建一个新的结构体
    fmt.Println(Books{"Go 语言", "www.runoob.com", "Go 语言教程", 6495407})

    // 也可以使用 key => value 格式
    fmt.Println(Books{title: "Go 语言", author: "www.runoob.com", subject: "Go 语言教程", book_id: 6495407})

    // 忽略的字段为 0 或 空
   fmt.Println(Books{title: "Go 语言", author: "www.runoob.com"})
}
  • 访问结构体成员,用点号.操作符,格式为:结构体.成员名
  • struct类似于java中的类

切片(Slice)

  • go数组的长度不可改变,go提供了一种灵活,功能强悍的内置类型切片(“动态数组”)。切片不需要说明长度var identifier []type或者用make()函数来创建切片
var slice1 []type = make([]type, len)

也可以简写为

slice1 := make([]type, len)

范围(Range)

  • Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对

Map(集合)

递归函数

类型转换

package main

import "fmt"

func main() {
   var sum int = 17
   var count int = 5
   var mean float32
   
   mean = float32(sum)/float32(count)
   fmt.Printf("mean 的值为: %f\n",mean)
}

接口

错误处理

package main

import (
    "fmt"
)

// 定义一个 DivideError 结构
type DivideError struct {
    dividee int
    divider int
}

// 实现 `error` 接口
func (de *DivideError) Error() string {
    strFormat := `
    Cannot proceed, the divider is zero.
    dividee: %d
    divider: 0
`
    return fmt.Sprintf(strFormat, de.dividee)
}

// 定义 `int` 类型除法运算的函数
func Divide(varDividee int, varDivider int) (result int, errorMsg string) {
    if varDivider == 0 {
            dData := DivideError{
                    dividee: varDividee,
                    divider: varDivider,
            }
            errorMsg = dData.Error()
            return
    } else {
            return varDividee / varDivider, ""
    }

}

func main() {

    // 正常情况
    if result, errorMsg := Divide(100, 10); errorMsg == "" {
            fmt.Println("100/10 = ", result)
    }
    // 当被除数为零的时候会返回错误信息
    if _, errorMsg := Divide(100, 0); errorMsg != "" {
            fmt.Println("errorMsg is: ", errorMsg)
    }

}

执行以上程序,输出结果为:

100/10 =  10
errorMsg is:  
    Cannot proceed, the divider is zero.
    dividee: 100
    divider: 0

并发

  • 支持并发,只需要通过go关键字来开启goroutine即可,goroutine 是轻量级线程
  • 所有的goroutine共享一个地址空间
  • 通道channel是用传递数据的一个数据结构,通道可用于两个goroutine之间通过传递一个指定类型的值来同步运行和通讯
ch <- v    // 把 v 发送到通道 ch
v := <-ch  // 从 ch 接收数据
           // 并把值赋给 v

PS:

1、欢迎访问我的个人站点:小白求学进阶

2、欢迎访问我的CSDN博客:小白求学进阶

3、微信公众号:

4、本文为原创文章,转载还需告知本人~谢谢

# Go  笔记 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×