Go语言特性分享(一)

114 阅读2分钟

一、前言

1.1 统一思想

图片.png

1.2 为什么需要学Go语言

图片.png

Go语言的优势

图片.png

Go语言不支持的特性

图片.png

Go语言特性衍生来源

图片.png

二、实践

2.1 Go语言编译环境设置

图片.png

2.2 控制结构

if

  • 基本形式
//基本写法
if condition1 {
    //do something
} else if condition2 {
    //do something
} else {
    //catch-all or default
}

//if 简短语句
if v:=x - 100;v<0{
    return v
}
  • switch
switch var1 {
  case val1://空分支
  case val2:
      fallthrough//执行case3中的f()
  case val3:
    f()
  default: //默认分支
   ……
}
  • for
//go语言只有一种循环:for
for i:=0;i<10;i++ {
    sum += i
}

//无限循环
for {
    if condition1 {
        break
    }
}

2.3 Go语言常用数据结构

常量和变量

  • 常量 const identifier type
  • 变量 var identifier type
//变量
var c, python, java bool

//变量初始化
var i,j int = 1,2

//短变量声明
c, python, java := true,false,"no!"

// := 可在函数内使用

类型转化和推导

// 数值转化
var i int = 42
var f float64 = float64(i)
var u uint = uint(f)

//类型推导
var i int;
j := i //j和i相等 j也是int

数组

//定义
var identifier[len] type
array :=[3]int{1,2,3}
//demo
func main() {
   array := [3]int{1, 2, 3}
   fmt.Println(array)
   fmt.Println("=========================")
   //=========================
   for i := 0; i < len(array); i++ {
      fmt.Println(array[i])
   }
   fmt.Println("=========================")
   //==========================
   array2 := [3]int{}
   for i := 0; i < len(array); i++ {
      array2[i] = i
   }
   fmt.Println(array)
}

切片

  • 切片是对数组一个连续片段的引用
  • 数组定义中不指定长度即为切片
    • var identifier []type
  • 切片在未初始化之前默认为nil, 长度为0
  • 常用方法
func main() {
   array := [5]int{1, 2, 3, 4, 5}
   slice := array[1:3]
   fmt.Printf("slice %+v\n", slice)

   fullSlice := array[:]
   result := deleteItem(fullSlice, 2)
   fmt.Printf("result: %+v\n", result)

   var slice2 []int
   slice2 = append(slice2, 1)
   slice2 = append(slice2, 2)
   fmt.Printf("slice2: %+v\n", slice2)
}

func deleteItem(slice []int, index int) []int {
   return append(slice[:index], slice[index+1:]...)
}

//构建切片
func main() {
   //new 返回指针地址
   //make 返回第一个元素,可预设内存空间,避免未来的内存拷贝
   slice := new([]int)
   slice2 := make([]int, 0)
   slice3 := make([]int, 10)
   slice4 := make([]int, 10, 20)

   fmt.Println(slice)
   fmt.Println(slice2)
   fmt.Println(slice3)
   fmt.Println(slice4)

}

图片.png

Map

func main() {
   //简单map
   myMap := make(map[string]string, 10)
   myMap["key1"] = "a"
   fmt.Println(myMap)

   //复杂
   myFuncMap := map[string]func() int{
      "funA": func() int {
         return 1
      },
   }
   fmt.Println(myFuncMap)
   //访问map
   value, exists := myMap["key1"]
   if exists {
      println(value)
   }

   for k, v := range myMap {
      println(k, v)
   }
}

结构体

func main() {
   s1 := Student{}
   p1 := &s1      //取指针地址
   student := *p1 //取值
   fmt.Println(student)

   s := new(Student) //new 出来直接是指针地址
   fmt.Println(*s)

   s.name = "nike"
   s.age = 18
   name := getName(*s)
   fmt.Println(name)
   
}

type Student struct {
   name string
   age  int
}

func getName(student Student) string {
   return student.name
}

type IF interface {
   getName() string
}

结构体标签

// MyType k8s APIServer 对所有资源的定义都用了json tag 和 protoBuff tag
type MyType struct {
   Name string `json:"name"`
}

func main() {
   mt := MyType{Name: "test"}
   myType := reflect.TypeOf(mt)
   name := myType.Field(0)
   tag := name.Tag.Get("json")
   println(tag)
}

类型别名

类似于枚举 图片.png

2.4 Go语言函数调用

init 函数

import (
   _ "GoDemoProject/src/MethodDemo/initDemo/a"
   _ "GoDemoProject/src/MethodDemo/initDemo/b"
   "fmt"
)

// init 只执行一次
func init() {
   fmt.Println("init main")
}

func main() {
   fmt.Println("main")
}


package a

import (
   _ "GoDemoProject/src/MethodDemo/initDemo/b"
   "fmt"
)

func init() {
   fmt.Println("a")
}



package b

import "fmt"

func init() {
   fmt.Println("b")
}

返回值

图片.png

package main

import "fmt"

func main() {
   err, result := method("bbb")
   if err == nil {
      fmt.Println(result)
   } else {
      fmt.Println(err)
   }
}

func method(input string) (err error, result string) {
   if input == "aaa" {
      err = fmt.Errorf("aaa is not allowed")
      return
   }
   result = input + input
   return nil, result
}

传递变长的参数

图片.png

func main() {

   var array []string
   array = append(array, "a", "b", "c")
   for index, value := range array {
      println(index, value)
   }
}

内置函数

图片.png

回调函数 callback

  • 函数作为参数传入其他函数,并在其他函数内部调用执行
    • strings.indexFunc(line, unicode.isSpace)
    • kubernetes controller的leaderelection
func main() {
   DoOperation(1, increase)
   DoOperation(1, decrease)

}

func increase(a, b int) {
   println("i result:", a+b)
}

func decrease(a, b int) {
   println("d result:", a-b)
}

func DoOperation(y int, f func(int, int)) {
   f(y, 1)
}

闭包

  • 匿名函数
  • 可以赋值给其他变量
    • x:=func(){}
  • 可以直接调用
    • func(x,y int){println(x+y)}(1,2)
  • 可作为函数返回值
    • func Add() (func(b int)int)

全局变量的特点:1.常驻内存 2. 污染全局

局部变量的特点:1.不常驻内存 2.不污染全局

而Go语言的闭包可以做到: 1.可以让变量常驻内存 2.可以让变量不污染全局

闭包
1.闭包是指有权访问另一个函数作用域中的变量的函数
2.创建闭包的常见方式就是在一个函数内部创建另一个函数, 内函数可以访问外函数的变量

注意:
闭包里作用域返回的局部变量不会被立刻销毁回收,但过度使用闭包可能会占用更多内存,导致性能下降。

func main() {
   result := add(1)
   println(result())
}

func add(a int) func() int {
   i := a + a
   return func() int {
      return i + 1
   }
}

方法

方法:作用在接收者上的函数

  • func(recv receiver_type) methodName(parameter_list)(return_value_list)
  • 使用场景
    • 很多场景下,函数需要的上下文可以保持在recevier属性中,通过定义recevier方法,该 方法可以直接访问recevier属性,减少参数传递需求
type Student struct {
   name string
   age  int
}

func (s Student) notify() {
   fmt.Printf("%v : %v \n\n", s.name, s.age)
}

func main() {
   //值调用
   s1 := Student{"jack", 18}
   s1.notify()

   //指针调用
   s2 := Student{"rose", 16}
   (&s2).notify()
}

图片.png

接口

图片.png

type IF interface {
   getName() string
}

type Student struct {
   name string
   age  int
}

func (s *Student) getName() string {
   return s.name
}

type Car struct {
   factory, model string
}

func (c *Car) getName() string {
   return c.factory + "-" + c.model
}

func main() {
   var interfaces []IF
   student := new(Student)
   student.name = "jack"
   student.age = 18
   interfaces = append(interfaces, student)

   car := new(Car)
   car.factory = "benz"
   car.model = "s"
   interfaces = append(interfaces, car)

   for _, f := range interfaces {
      fmt.Println(f.getName())
   }
}

图片.png

反射机制

图片.png

type Student struct {
   name string
   age  int
}

func (s Student) getName() string {
   return s.name
}

func main() {
   myMap := make(map[string]string, 10)
   myMap["A"] = "aaa"
   t := reflect.TypeOf(myMap)
   fmt.Println("type:", t)

   v := reflect.ValueOf(myMap)
   fmt.Println("value", v)

   //基于struct的反射
   student := Student{"jack", 18}
   v1 := reflect.ValueOf(student)
   for i := 0; i < v1.NumField(); i++ {
      fmt.Printf("Filed %d: %v\n", i, v1.Field(i))
   }
   for i := 0; i < v1.NumMethod(); i++ {
      fmt.Printf("Method %d: %v\n", i, v1.Method(i))
   }
}

图片.png

json 编码与解码

2.5 常用语法

2.6 多线程