go入门语法

编译

go build xxx.go 即可编译

go build -o xxx.exe xxx.go 指定编译后的文件名

字符串类型

go的字符串是由 字节 组成的
go中的字符串一旦赋值是不能改变的

package main //当前包名
import (
	"fmt"
)

func main() {
	s := "sf"
	s[0] = 'a'   //报错  不可修改
}

反引号 让字符串保持原格式

package main //当前包名
import (
	"fmt"
)

func main() {
	s := `
	import (
		"fmt"
		"unsafe"
	)
	`

}

基本数据类型转换

	var num int = 100
	var num1 float32 = float32(num)
	fmt.Printf("%T %f", num1, num1)

基本数据类型和string互相转换

	var num int = 100
	s := fmt.Sprintf("数字转换:%d", num)
	fmt.Printf("%s", s)
	
	var s string = "100"
	n, _ := strconv.Atoi(s)
	fmt.Printf("转换后的数字:%d", n)

值类型和引用类型

值类型:基本类型 int string 数组 结构体 在栈中存储
引用类型:指针 silence切片map 管道interface 通常在堆中存储

switch语句

	n := 1
	switch n {
	case 1, 2:   //可以匹配多个条件
		fmt.Print("值是1 或者2")
		fmt.Print("结束")
		//不需要写break
	case 3:
		fmt.Print("值是3")
		fmt.Print("结束")
	default:
		fmt.Print("其余值")
		fmt.Print("结束")

	}

main函数

package main //当前包名

//导多个包格式
import (
	"fmt"
	"time"
)

func main() {
	fmt.Printf("hello")
	time.Sleep(time.Second)
}

4中声名变量的方式和多变量声名

package main //当前包名

//导多个包格式
import (
	"fmt"
)

func main() {
	//方式1:声名一个变量 默认的值是0
	var a int
	fmt.Println(a)
	fmt.Printf("type of a =%T\n", a) //输出变量类型

	//方式2:声名一个变量 初始化一个值
	var b int = 100
	fmt.Println(b)
	fmt.Printf("type of b =%T\n", b)

	//方式3:声名时直接赋值,根据值判断类型,不需写类型
	var c = 200
	fmt.Println(c)
	fmt.Printf("type of c =%T\n", c)

	//方式4:省去var关键字,直接自动匹配  (常用方法) 不能用于声名全局变量
	d := 300
	fmt.Println(d)
	fmt.Printf("type of d =%T\n", d)

	//声名多个变量
	var e, f int = 1, 2
	fmt.Println(e, f)

	var g, h = 3, "dale"
	fmt.Println(g, h)

	var (
		x int = 5
		y int = 6
	)
	fmt.Println(x, y)

}

字符串常用函数

在这里插入图片描述

const实现枚举功能

package main //当前包名

import "fmt"

//枚举
const (
	Arrow = iota // 开始生成枚举值, 默认为0
	Shuriken
	SniperRifle
	Rifle
	Blower
)

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

多返回值的3种写法

package main //当前包名

import "fmt"

//函数名 形参 形参  返回值
func add(a int, b int) int {
	return a + b
}

//函数名 形参 形参  返回值  返回值(匿名)
func sub(a int, b int) (int, int) {
	return a - b, 1
}

//函数名 形参 形参  返回值  返回值(返回值带名字)
func del(a int, b int) (r1 int, r2 int) {
	r1 = a - b
	r2 = 5
	return
}

func main() {
	a := add(3, 2)
	fmt.Println(a)

	b, c := sub(6, 3)
	fmt.Println(b, c)
}

匿名导包

import(
_ "fmt"
)
匿名导入包 但是不使用包的导出函数,仅调用init方法 

给包起别名

import(
mylib "fmt"
)

//使用的时候
mylib.Print("test")

匿名导入包 但是不使用包的导出函数,仅调用init方法 

defer

defer相当于final,在函数的最后执行 用于清理资源

package main //当前包名
import "fmt"

func test() {
	defer fmt.Println("test end1")
	defer fmt.Println("test end2")
	fmt.Println("test run")
}

func main() {
	test()
}

执行结果 test run test end2 test end1

数组和动态数组

在这里插入图片描述

package main //当前包名
import "fmt"

func main() {
	//固定长度数组
	var arr [10]int
	for i := 1; i < len(arr); i++ {
		arr[i] = i
	}
	//第一种遍历方式
	for i := 1; i < len(arr); i++ {
		fmt.Println(arr[i])
	}

	//第二种遍历方式
	for index, value := range arr {
		fmt.Println(index, value)
	}
}

package main //当前包名
import "fmt"

//动态数组传参
func print(arr []int) {
	//如果某一个返回值不使用,可以用_来表示匿名
	for _, value := range arr {
		fmt.Println(value)
	}
	//切片是引用传递  修改值会影响原始值
	arr[0] = 100
}

func main() {
	//动态数组  slice:切片
	arr := []int{1, 2, 3, 4}
	print(arr)

	//会输出100
	fmt.Println(arr[0])
}

slice切片的4种声名和定义方式

package main //当前包名
import "fmt"

func main() {
	//切片第1种方式:直接给定大小
	sli1 := []int{1, 2, 3, 4}
	fmt.Println(sli1[0])

	//第2种 申明sli2是一个切片,但是没有分配空间 使用make来开辟空间
	var sli2 []int
	sli2 = make([]int, 3)
	sli2[0] = 100
	fmt.Println(sli2[0])

	//第3种 申明sli2是一个切片并且使用make来开辟空间
	var sli3 []int = make([]int, 3)
	sli3[0] = 100
	fmt.Println(sli3[0])

	//第4种 使用类型推导
	sli4 := make([]int, 3)
	sli4[0] = 100
	fmt.Println(sli4[0])
	
	arr1 := [...]int{1, 2, 3}    //定义数组 类型 [3]int
	arr2 := arr1[:]				 //arr2 是切片类型  []int
	fmt.Printf("%T\n", arr2)
}

判断切片是否为空

	sli1 := []int{1, 2, 3, 4}
	fmt.Println(sli1[0])

	if sli1 == nil {
		fmt.Println("slice是空的")
	}

切片的追加和截取

package main //当前包名
import "fmt"

func main() {
	//sli1 len 是3 ,cap(容量) 是5
	sli1 := make([]int, 3, 5)
	sli1[0] = 0
	sli1[1] = 1
	sli1[2] = 2
	sli1 = append(sli1, 6) //追加一个元素6  len变成4 cap 还是5
	//如果append后len大于cap,那么切片的容量就会再次增加一个cap的大小

	//切片的截取  从第0个元素开始截取,取的大小是2个.取出的元素是第0和第1个
	//这种情况是浅拷贝,修改sli2元素的值,sli1里面的也会改变
	sli2 := sli1[0:2]
	fmt.Println(sli2)

	//深拷贝
	sli3 := make([]int, 3)
	copy(sli3, sli1)
	fmt.Println(sli3)
}

在这里插入图片描述

map的3中声名和定义方式

package main //当前包名
import "fmt"

func main() {

	//方式1
	var myMap1 map[string]string
	if myMap1 == nil {
		fmt.Println("map是空的")
	}

	//在使用map前.需要先用make给map分配数据空间
	myMap1 = make(map[string]string, 10)
	myMap1["1"] = "java"
	myMap1["2"] = "c++"
	fmt.Println(myMap1)

	//方式2
	myMap2 := make(map[int]string)
	myMap2[1] = "go"
	myMap2[2] = "delphi"
	fmt.Println(myMap2)

	//方式3
	myMap3 := map[string]string{
		"1": "php",
		"2": "python",
	}
	fmt.Println(myMap3)

}

map的增删改查

package main //当前包名
import "fmt"

func main() {

	var myMap1 map[string]string

	//在使用map前.需要先用make给map分配数据空间
	myMap1 = make(map[string]string, 10)
	myMap1["1"] = "java"
	myMap1["2"] = "c++"

	//添加
	myMap1["3"] = "go"

	//删除
	delete(myMap1, "1")

	//修改
	myMap1["2"] = "c"

	//遍历
	for key, value := range myMap1 {
		fmt.Println(key, value)
	}
}

map切片

map会自动扩容 map的切片不行 需要使用append

	a := make([]map[int]string, 2)    //分配map切片
	b := map[int]string{1: "djaigen"} //一个map对象
	a[0] = b                          //map切片中添加一个map对象

struct的4种声明方式

package main 
import (
	"fmt"
)

type Person struct {
	Name string
	Age  int
}

func main() {

	var Per1 Person
	Per1.Age = 20

	var Per2 Person = Person{"dale", 30}
	Per2.Age = 20

	Per3 := &Person{"dale", 30}
	Per3.Age = 20

	Per4 := new(Person)
	Per4.Age = 20
	fmt.Println(Per4)
}

new 一个struct

package main //当前包名
import "fmt"

var (
	app = NewApp()
)

func NewApp() *App {
	app := new(App)
	app.auth = "dale"
	app.title = "happy"
	return app
}

type App struct {
	title string
	auth  string
}

func main() {

	//%v 可以打印任何结构
	fmt.Printf("%v\n", *app)   //这里使用了解指针
}

类的封装

package main //当前包名
import "fmt"

type Hero struct {
	//如果类的属性首字母大写,代表外部可以访问.小写属性只能在类的内部使用
	Name  string
	Level int
}

//给结构体绑定方法
func (hero *Hero) GetName(Name string) string {
	return hero.Name
}

func (hero *Hero) SetName(Name string) {
	hero.Name = Name
}

func (hero *Hero) Show() {
	fmt.Println(hero.Name, hero.Level)
}

func main() {
	dale := Hero{"dale", 100}
	dale.Show()
	dale.SetName("daying")
	dale.Show()
}

继承

package main //当前包名
import "fmt"

type Human struct {
	//如果类的属性首字母大写,代表外部可以访问.小写属性只能在类的内部使用
	Name string
	sex  string
}

//给结构体绑定方法
func (human *Human) Eat() {
	fmt.Println("eat")
}

type SuperMan struct {
	Human //SuperMan 继承Human类的方法
	level int
}

func main() {
	dale := SuperMan{Human{"dale", "female"}, 100}
	dale.Eat()
}

多态

package main //当前包名
import "fmt"

//本质是一个指针
type AnimalIF interface {
	GetName()
}

type Cat struct {
}

//给结构体绑定方法
func (cat *Cat) GetName() {
	fmt.Println("cat")
}

type Dog struct {
}

//给结构体绑定方法
func (dog *Dog) GetName() {
	fmt.Println("dog")
}

func main() {
	var animal AnimalIF //接口的数据类型,父类指针
	animal = &Cat{}
	animal.GetName()

	animal = &Dog{}
	animal.GetName()
}

万能数据类型 类型断言

package main //当前包名
import "fmt"

//万能数据类型 相当于void *
func Test(arg interface{}) {
	value, ok := arg.(string)   //类型断言 如果是string会转换成功 如果失败  ok是false
	if !ok {
		fmt.Println("不是字符串类型")
	} else {
		fmt.Println("字符串类型", value)
	}
}
func main() {
	Test(111)
	Test("hello")
}

反射

package main //当前包名
import (
	"fmt"
	"reflect"
)

// 万能数据类型 相当于void *
func Test(arg interface{}) {
	fmt.Println(reflect.TypeOf(arg), reflect.ValueOf(arg))
}
func main() {
	Test(111)
	Test("hello")
}

转json

package main //当前包名
import (
	"encoding/json"
	"fmt"
)

// 可以给字段定义标签
type resume struct {
	Name string `json:"name"`
	Sex  string `json:"sex"`
}

func main() {
	a := resume{"dale", "female"}
	jsonstr, err := json.Marshal(a)
	if err == nil {
		fmt.Printf("%s", jsonstr)
	}

}

互斥锁

package main //当前包名
import (
	"fmt"
	"sync"
	"time"
)

var (
	Sum  int
	lock sync.Mutex
)

func test() {
	lock.Lock()
	Sum = Sum + 1
	lock.Unlock()
}

func main() {

	for i := 0; i < 50000; i++ {
		go test()
	}

	time.Sleep(time.Second * 2)
	fmt.Println(Sum)
}

channel

package main //当前包名
import (
	"fmt"
	"time"
)

func main() {
	//定义一个channel 类型是int 无缓冲,chan两边的代码无论谁先运行到chan这里都需要等待
	c := make(chan int)
	//c := make(chan int,3)  带缓冲的channel
	go func() {
		time.Sleep(time.Second)
		c <- 100 //把值写入到管道
		close(c) //关闭channel
	}() //最后这个() 代表调用这个匿名函数
	num := <-c //从管道读取数据   阻塞
	fmt.Println(num)
}

channel与range

package main //当前包名
import (
	"fmt"
)

func main() {
	//定义一个channel 类型是int 无缓冲,chan两边的代码无论谁先运行到chan这里都需要等待
	c := make(chan int)
	//c := make(chan int,3)  带缓冲的channel
	go func() {
		for i := 0; i < 5; i++ {
			c <- i

		}
		close(c) //关闭channel
	}() //最后这个() 代表调用这个匿名函数

	//for 无限循环
	// for {
	// 	if data, ok := <-c; ok {
	// 		fmt.Println(data) //成功读到数据 就输出数据
	// 	} else {
	// 		break //channel关闭了就退出
	// 	}

	// }

	//也可以用range来接收
	for data := range c {
		fmt.Println(data) //成功读到数据 就输出数据
	}
	fmt.Println("channel已关闭")
}

channel实现等待

package main //当前包名
import (
	"fmt"
)

func readData(a chan int, b chan int) {
	for {
		if data, ok := <-a; ok {
			fmt.Printf("读取到的数据%d\n", data)
		} else {
			fmt.Printf("管道关闭\n")
			//读取完了 通知关闭管道了
			close(b)
			break
		}
	}

}

func writeData(a chan int) {
	for i := 0; i < 10; i++ {
		a <- i
	}
	close(a)
}

func main() {
	a := make(chan int, 10)
	b := make(chan int, 1)
	go readData(a, b)
	go writeData(a)

	//等待数据读取完  然后退出
	if data, ok := <-b; ok {
		fmt.Printf("读取到的数据%d\n", data)
	} else {
		fmt.Printf("关闭了\n")
	}
}

在这里插入图片描述

在这里插入图片描述

ubuntu安装golang apt-get install golang
go设置开启gomodules go env -w GO111MODULE=on
go设置国内代理 go env -w GOPROXY=https://goproxy.cn,direct

调用自己本地写的包

先在项目根目录初始化gomodule go mod init github.com/9GProxy
github.com/9GProxy是自己随便起的名字

然后项目下有一个server目录,里面有一个server.go 包名server
在这里插入图片描述

在这里插入图片描述

在main包中调用自己写的包

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值