go初级接触

195 阅读5分钟

go的语法基础

hello world

package main

import "fmt"

func main() {
   fmt.Println("hello world")

   // 简易版
   println("hello world")
}

/**
go run [path] 直接运行程序
go build [path] 将程序编译成二进制,会变成一个exe文件,通过.[path]执行该程序
*/

1.Go语言使用包来组织源代码的,并实现命名空间的管理,任何一个Go语言程序必须属于一个包,即每个go程序的开头要写上package <pkg_name>。

2.fmt--是一个控制输出的包

类型

package main

func main() {
   // 变量声明的方式,以整型为例子
   var intNum1 int = 0
   var intNum2, intNum3 int = 1, 2
   var intNum4 = 3
   // 简易声明,类型自动推断
   intNum5 := 5

   println(intNum1)
   println(intNum2, intNum3)
   println(intNum4)
   println(intNum5)
   
   //go中一次声明多个变量
   var (
        a string
        b int
        c bool
        d float32
    )
    
    //go多个变量声明并且赋值
    var name,sex = "gogo", 1


   // 常量
   const PI float32 = 3.1415926
   println(PI)

   // 布尔
   flag := false
   println(flag)

   // 浮点型64
   var float64Num float64
   println(float64Num)

   // 浮点型32
   float32Num := float32(float64Num)
   println(float32Num)

   // 字符串
   str := "你好"
   str += "世界"
   println(str)
   
   //一个常量计数器-- iota
}

/**

Go是一门强类型的语言
变量声明可以省略类型,但不能省略var关键字,类型省略可以根据变量的值自动推导
*/

if-else

package main

func main() {
   // if - else
   if 7%2 == 0 {
      // 偶数
      println("7 is even")
   } else {
      // 奇数
      println("7 is odd")
   }

   // if - else if - else
   // num给其一个初始条件
   if num := 9; num < 0 { // 如果 num < 0--这里可以直接赋值
      println(num, "is negative") // 输出它是一个负数
   } else if num == 0 {
      println(num, "is zero") // 输出它是一个0
   } else {
      println(num, "is positive") // 输出它是一个正数
   }
}

循环

//go没有while,do while, 只能使用for
package main

func main() {
  //这个就等同于while(true)
   for {
      println(1)
      break
   }

   // 打印0-9
   for i := 0; i < 10; i++ {
      println(i)
   }
}

switch

package main

import "time"

func main() {
   a := 2
   switch a {
   case 1:
      println("one")
   case 2:
      println("two")
   default:
      println("不知道")
   }

   t := time.Now()//获取当前时间
   println(t)
   // 特殊用法,可以取代if - else
   switch {
   case t.Hour() < 12:
      println("早于中午")
   default:
      println("晚于中午")
   }
}

/**
switch自带一个break,这是和其他语言不同之处
*/

数组

package main

import (
    "fmt"
)

var arr0 [5]int = [5]int{1, 2, 3}
var arr1 = [5]int{1, 2, 3, 4, 5}
var arr2 = [...]int{1, 2, 3, 4, 5, 6}
var str = [5]string{3: "hello world", 4: "tom"}

func main() {
    a := [3]int{1, 2}           // 未初始化元素值为 0。
    b := [...]int{1, 2, 3, 4}   // 通过初始化值确定数组长度。
    c := [5]int{2: 100, 4: 200} // 使用引号初始化元素。--蛮特别的
    d := [...]struct {
        name string
        age  uint8
    }{
        {"user1", 10}, // 可省略元素类型。
        {"user2", 20}, // 别忘了最后一行的逗号。
    }
    fmt.Println(arr0, arr1, arr2, str)
    fmt.Println(a, b, c, d)
}
/*
  [1 2 3 0 0] [1 2 3 4 5] [1 2 3 4 5 6] [   hello world tom]
  [1 2 0] [1 2 3 4] [0 0 100 0 200] [{user1 10} {user2 20}]
**/
//多维数组
package main

import (
    "fmt"
)

var arr0 [5][3]int
var arr1 [2][3]int = [...][3]int{{1, 2, 3}, {7, 8, 9}}

func main() {
    a := [2][3]int{{1, 2, 3}, {4, 5, 6}}
    b := [...][2]int{{1, 1}, {2, 2}, {3, 3}} // 第 2 纬度不能用 "..."。
    fmt.Println(arr0, arr1)
    fmt.Println(a, b)
}
/*
    [[0 0 0] [0 0 0] [0 0 0] [0 0 0] [0 0 0]] [[1 2 3] [7 8 9]]
    [[1 2 3] [4 5 6]] [[1 1] [2 2] [3 3]]  
*/

slice切片

package main

import "fmt"

func main() {
   // 用make创建切片,需要指定初始长度
   s := make([]string, 3)
   s[0] = "a"
   s[1] = "b"
   s[2] = "c"
   fmt.Println("get:", s[2])   // c
   fmt.Println("len:", len(s)) // 3

   // 新增,需要用一个切片变量接收,容量不够会扩容,返回一个新的slice
   s = append(s, "d")
   sNew := append(s, "e", "f")
   fmt.Println(sNew)

   // copy
   a := make([]string, len(sNew))
   copy(a, sNew)
   fmt.Println(a)

   // 切片操作
   fmt.Println(a[:])   // 所有
   fmt.Println(a[2:5]) // 区间[2,5)
   fmt.Println(s[:3])  // [0,3)
   fmt.Println(s[1:])  // 1到结尾

   // 简易定义
   good := []string{"g", "o", "o", "d"}
   fmt.Println(good)
   good = append(good, "!")
   fmt.Println(good)
   // 区别数组:   b := [5]int{1, 2, 3, 4, 5},是需要指定长度的
}

/**
切片是一个可变长数组,不用指定其长度。[]类型
和python很是相似,但这个没有负数的索引
*/

map

package main

import "fmt"

func main() {
   // key string, value int
   m := make(map[string]int)
   m["one"] = 1
   m["two"] = 2
   fmt.Println(m)
   fmt.Println(len(m))     //2
   fmt.Println(m["one"])   //1
   fmt.Println(m["two"])   //2
   fmt.Println(m["three"]) //0

   // ok 获取map中是否有这个key存在
   r, ok := m["three"]
   //fmt.Println(r)
   //fmt.Println(ok)
   fmt.Println(r, ok)

   // 删除key为one
   delete(m, "one")

   // 简易定义
   m2 := map[string]int{"one": 1, "two": 2}
   fmt.Println(m2)

   // 遍历map,同理可以遍历数组--遍历很特别
   for key, value := range m {
      println(key, value) // key,value
   }
}

/**
map 是无序的,Map呢这个和c++中stl库中保持高度一致,理解不差
但是可以发现这边的map方法明显少,但是同时使用多个变量去获取倒是多,可能是语言特色
*/

函数

函数声明包含一个函数名,参数列表, 返回值列表和函数体。如果函数没有返回值,则返回列表可以省略。函数从第一条语句开始执行,直到执行return语句或者执行函数的最后一条语句。

函数可以没有参数或接受多个参数。

注意类型在变量名之后 。

当两个或多个连续的函数命名参数是同一类型,则除了最后一个类型之外,其他都可以省略。

函数可以返回任意数量的返回值。

使用关键字 func 定义函数,左大括号依旧不能另起一行。

func test(x, y int, s string) (int, string) {
    // 类型相同的相邻参数,参数类型可合并。 多返回值必须用括号。
    n := x + y          
    return n, fmt.Sprintf(s, n)
}

//函数是第一类对象,可作为参数传递。建议将复杂签名定义为函数类型,以便于阅读。

import "fmt"

func test(fn func() int) int {
    return fn()
}
// 定义函数类型。
type FormatFunc func(s string, x, y int) string 

func format(fn FormatFunc, s string, x, y int) string {
    return fn(s, x, y)
}

func main() {
    s1 := test(func() int { return 100 }) // 直接将匿名函数当参数。

    s2 := format(func(s string, x, y int) string {
        return fmt.Sprintf(s, x, y)
    }, "%d, %d", 10, 20)

    println(s1, s2)
}
//    100 10, 20

结构体

也和c++差不多

    type 类型名 struct {
        字段名 字段类型
        字段名 字段类型
        …
    } 
type person struct {
    name string
    city string
    age  int8
}

func main() {
    var p1 person
    p1.name = "pprof.cn"
    p1.city = "北京"
    p1.age = 18
    fmt.Printf("p1=%v\n", p1)  //p1={pprof.cn 北京 18}
    fmt.Printf("p1=%#v\n", p1) //p1=main.person{name:"pprof.cn", city:"北京", age:18}
} 

指针

这个c++指针类似,*和&符号使用

new和make:

1.二者都是用来做内存分配的。 2.make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身; 3.而new用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针。

func main() {
	var a int
	fmt.Println(&a)//输出a的地址
	var p *int
	p = &a  //将指针p指向a这样a和p指向的就是同一块内存地址
	*p = 20
	fmt.Println(a)
}