Golang

Golang 专栏收录该内容
1 篇文章 0 订阅

Golang

一、Golang环境安装

  1. Golang下载地址
  2. IDE推荐 JetBrain GoLand
  3. 设置GoPath

二、Go项目目录结构

go项目目录结构

三、Hello world

package main  // 定义了包名,表示这个文件属于哪个包,每个Go程序都包含一个名为main的包
import "fmt" // 导入包
func main(){
	fmt.Println("Hello World!")
}

Go函数的定义

func  函数名(参数列表)(返回值列表){
	//函数体
}
// 实例
func Compute(value1 int, value2 float32)(result float64 err error){
	//函数体
}

四、Go语言变量

声明变量的一般形式是使用var关键字
var 变量名 变量类型var 变量1,变量2 变量类型

变量声明

// 1、若没有初始化,则变量默认为0
var v_name v_type
v_name = value

var v_name1 v_name2 v_type
v_name1, v_name2 = value1, value2

// 2、直接初始化
var v_name v_type = value
var v_name1, v_name2 v_type = value1, value2

// 3、自行判断变量类型
var v_name = value
var v_name1, v_name2 = value1, value2

// 4、省略var
v_name := value
v_name1, v_name2 := value1, value2

//因式分解关键字的写法一般用于声明全局变量
var (
	v_name1 v_type1
	v_name2 v_type2
)

常量声明

const 变量名 [变量类型] = value

const a, b, c = 1, false, "str"

//常量还可以用作枚举
const (
	a = 0
	b = 1
	c = 2
)

iotaconst关键字出现时被重置为0,并在const中每新增一行常量声明将是iota计数一次

const (
	a = iota // a = 0
	b = iota // b = 1
	c = iota // c = 2
)

// 可以简写成
const (
	a = iota
	b
	c
)

变量类型

  • 布尔类型:bool
  • 整型:int8、byte、int16、int、uint、uintptr
  • 浮点类型:float32、float64
  • 复数类型:complex64、complex128
  • 字符串:string
  • 字符类型:rune
  • 错误类型:error

数组

[32]byte // 长度为32的数组,每个元素为一个字节
[2*N]struct{x, y int32} //复杂类型数组
[1000]*float64 //指针数组
[3][5]int //二维数组
[2][2][2]float64 // 三维数组

五、流程控制

条件语句

if a < 5 {
	return 0
}else {
	return 1
}
if statement;condition {
	// do something
}
// 例
if val, ok := map[key]; ok {
	//do something
}

选择语句

switch i {
	case 0:
		fmt.Printf("0")
	case 1:
		fmt.Printf("1")
	case 2:
		fallthrough //使用fallthrough会强制执行后面的case语句,而不会判断下一条的case的表达式结果时候为true
	default:
		fmt.Printf("Default")
}

循环语句

sum := 0
for i:=0; i<10; i++ {
	sum += i
}

// for循环的range格式可以对slice、map、数组、字符串等进行迭代循环,格式为
for key, value := range oldMap {
	newMap[key] = value
}

sum := 0
for {
	sum++
	if sum > 100 {
		break
	}
}

六、函数

函数定义

func function_name([parameter list]) [return_types] {
	函数体
}

七、Go语言数组

// var variable_name [SIZE] variable_type
var balance [10] float32

//初始化数组
var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
balance := [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
//长度不确定可以通过...代替数组长度
balance := [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

八、Go语言结构体(struct)

//定义结构体
type struct_variable_type struct {
	member definition
	member definition
	...
	member definition
}

// 一旦定义了结构体就可以用于变量的声明
variable_name := structure_variable_type {value1, value2,...,valuen}

//实例
type Books struct {
	title string
	author string
	subject string
	book_id int
}

abook := Books{"Go", "www.runoob.com", "Go语言教程"123456}
bbook := Books{title:"Go", author:"www.runoob.com", subject:"Go语言教程", book_id:123456}

//访问结构体成员 结构体.成员名 abook.title

JSON

1. struct -> json 序列化

	type Movie struct {
		Name  string
		Year  int
		actor []string
	}

	var movies = []Movie{
		{Name: "movie1", Year: 1999, actor: []string{"zhangsan", "lisi"}},
		{Name: "movie2", Year: 2000, actor: []string{"wangwu", "zhaoliu"}},
	}

	data, err := json.Marshal(movies) // 序列化
	if err != nil {
		fmt.Println("Json parse error")
		return
	}
	fmt.Println(movies)      // [{movie1 1999 [zhangsan lisi]} {movie2 2000 [wangwu zhaoliu]}]
	fmt.Printf("%s\n", data) // [{"Name":"movie1","Year":1999},{"Name":"movie2","Year":2000}]
	//这里的打印结果可以看出一个问题: actor属性并没有体现出来,这是因为JSON在处理struct转换的时候,只会处理属性名为大写的属性,小写的直接跳过不处理。

上面这个例子中,json序列化时会忽略小写开头的结构体成员,如果想要在json处理时显示成员为小写或别名,可以显示地为其添加标签:

	type Movie2 struct {
		Name  string
		Year  int
		Actor []string `json:"actor"`
	}
	var movies2 = []Movie2{
		{Name: "movie1", Year: 1999, Actor: []string{"zhangsan", "lisi"}},
		{Name: "movie2", Year: 2000, Actor: []string{"wangwu", "zhaoliu"}},
	}
	data2, _ := json.Marshal(movies2)
	fmt.Printf("%s\n", data2) // [{"Name":"movie1","Year":1999,"actor":["zhangsan","lisi"]},{"Name":"movie2","Year":2000,"actor":["wangwu","zhaoliu"]}]

2. json -> struct 反序列化

    // 沿用上面例子的变量和结构体
	//var movies3 Movie2
	// 这里犯了一个错误,导致运行报错.记一笔:
	// 将变量定义为Movie2结构体类型之后去接收这里的data2的json反序列化数据时,报错:json: cannot unmarshal array into Go value of type main.Movie2
	// 原因为: 当json串处理之后的结果是数组类型的时候,不能直接赋值给struct类型的值,因此,这里定义的movies3变量应该是[]Movie2的slice类型。go语言之中类型必须严格匹配,注意!
	// 另外,除了这里的unmarshal方式之外,还有一种json.Decoder的方式可以依次从字节流里逐个解码多个json对象,这个在后面的例子json_template.go中做解释。

	var movies3 []Movie2
    
	err2 := json.Unmarshal(data2, &movies3)
	if err2 != nil {
		fmt.Println("Json parse error", err2)
	}
	fmt.Printf("%v\n", movies3) // [{movie1 1999 [zhangsan lisi]} {movie2 2000 [wangwu zhaoliu]}]
	fmt.Println(movies3[0].Year)      // 1999

3. 可以选择的控制字段

//可以选择的控制字段有三种:
// -:不要解析这个字段
// omitempty:当字段为空(默认值)时,不要解析这个字段。比如 false、0、nil、长度为 0 的 array,map,slice,string
// FieldName:当解析 json 的时候,使用这个名字
type StudentWithOption struct {
    StudentId      string //默认使用原定义中的值
    StudentName    string `json:"sname"`           // 解析(encode/decode) 的时候,使用 `sname`,而不是 `Field`
    StudentClass   string `json:"class,omitempty"` // 解析的时候使用 `class`,如果struct 中这个值为空,就忽略它
    StudentTeacher string `json:"-"`               // 解析的时候忽略该字段。默认情况下会解析这个字段,因为它是大写字母开头的
}

九、数组切片(Slice)(动态数组)

// 定义切片
var identifier []type
//也可以使用make()函数创建切片
slice1 := make([]type, length, capacity) // capacity是容量,可选

// 创建一个初始元素个数为5的数组切片,元素初始值为0:
mySlice1 := make([]int, 5)

//创建一个初始元素个数为5的数组切片,元素初始值为0,并预留10个元素的存储空间:
mySlice2 := make([]int, 5, 10) 

切片初始化

s := []int {1,2,3}
s := arr[:]

切片可以用len()获得长度,cap()测量切片最长可以达到多少

append()和copy()函数

numbers = append(numbers, 0) // numbers中添加0
copy(numbers1, numbers) // 拷贝numbers1的内容到numbers

十、Map(集合)

类似于python的dict

//定义Map
// 申明变量,默认map是nil
var map_variable map[key_data_type]value_data_type

// 使用make函数
map_variable := make(map[key_data_type]value_data_type)

//实例
var countryCapitalMap map[string]string
countryCapitalMap = make(map[string]string)
/* map插入key - value对,各个国家对应的首都 */
countryCapitalMap [ "France" ] = "巴黎"
countryCapitalMap [ "Italy" ] = "罗马"
countryCapitalMap [ "Japan" ] = "东京"
countryCapitalMap [ "India " ] = "新德里"

/*使用键输出地图值 */
for country := range countryCapitalMap {
    fmt.Println(country, "首都是", countryCapitalMap [country])
}

/*查看元素在集合中是否存在 */
capital, ok := countryCapitalMap [ "American" ] /*如果确定是真实的,则存在,否则不存在 */

// 删除元素
delete(countryCapitalMap, "France")

十一、接口

定义

/* 定义接口 */
type interface_name interface {
   method_name1 [return_type]
   method_name2 [return_type]
   method_name3 [return_type]
   ...
   method_namen [return_type]
}

/* 定义结构体 */
type struct_name struct {
   /* variables */
}

/* 实现接口方法 */
func (struct_name_variable struct_name) method_name1() [return_type] {
   /* 方法实现 */
}
...
func (struct_name_variable struct_name) method_namen() [return_type] {
   /* 方法实现*/
}

实例

package main

import (
    "fmt"
)

type Phone interface {
    call()
}
/* ....................*/
type NokiaPhone struct {
}

func (nokiaPhone NokiaPhone) call() {
    fmt.Println("I am Nokia, I can call you!")
    //相当于NokiaPhone实例化了nokiaPhone, 并且有call()的方法
}
/* ....................*/
type IPhone struct {
}

func (iPhone IPhone) call() {
    fmt.Println("I am iPhone, I can call you!")
}
/* ....................*/
func main() {
    var phone Phone

    phone = new(NokiaPhone) //new 可以实例化对象实例
    phone.call()

    phone = new(IPhone)
    phone.call()

}

在上面的例子中,我们定义了一个接口Phone,接口里面有一个方法call()。然后我们在main函数里面定义了一个Phone类型变量,并分别为之赋值为NokiaPhoneIPhone。然后调用call()方法。

十二、Go并发

go关键字用于开启goroutinegoroutine是轻量级线程;
语法格式
go 函数名(参数列表)

go f(x, y, z)
//开启一个新的goroutine
f(x, y, z)
package main

import (
        "fmt"
        "time"
)
func say(s string) {
        for i := 0; i < 5; i++ {
                time.Sleep(100 * time.Millisecond)
                fmt.Println(s)
        }
}

func main() {
        go say("world")
        say("hello")
}

通道(channel)

channel是用来传递数据的一个数据结构,可用于两个goroutine之间通过传递一个指定类型的值来同步运行和通信,操作符<-用于指定通道的方向,发送或接收,如果为指定方向则为双向通道。

ch := make(chan int) //声明通道用chan关键字
ch <- v //把v发送到通道ch
v := <-ch //从ch接收数据并把值赋给v

//也可以指定缓冲区的大小
ch := make(chan int, 100)

// 可以关闭通道
close(ch)
  • 0
    点赞
  • 0
    评论
  • 7
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页

打赏作者

陈陈的肥猫

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值