Go语言入门基础语法

✅作者简介:CSDN内容合伙人、信息安全专业在校大学生🏆
🔥系列专栏 :
📃新人博主 :欢迎点赞收藏关注,会回访!
💬舞台再大,你不上台,永远是个观众。平台再好,你不参与,永远是局外人。能力再大,你不行动,只能看别人成功!没有人会关心你付出过多少努力,撑得累不累,摔得痛不痛,他们只会看你最后站在什么位置,然后羡慕或鄙夷。


环境配置

下载安装Go

  1. 无脑安装就行,地址:https://studygolang.com/dl

image.png

  1. 查看安装是否成功

在这里插入图片描述

  1. 设置环境变量

image.png
下面这个是存放默认项目文件和第三方库文件的地址? 随便新建一个目录就行(最好是的你的代码目录)
注意下面这个用弄两边:
image.png
image.png
然后在gopath目录下新建三个空文件夹:
image.png

  1. 检验:

在这里插入图片描述

下载安装GoLand

https://www.jetbrains.com/go/download/download-thanks.html
无脑安装

测试

  1. go run HelloWorld.go
package main

import "fmt"

func main(){
    fmt.Println("Hello World!")
}

在这里插入图片描述

  1. Goland

在这里插入图片描述

基础语法

注释

// 我是单行注释

/*
	我是多行注释
    我是多行注释
*/

变量

  1. 定义风格
var name type
//定义一个字符串变量 name
var name String
//定义一个数字类型变量 int
var age int
// 批量定义
var (
		name string
		age  int
		addr string
	)
  1. 短变量声明并初始化
// 这是Go语言的推导声明写法,编译器会自动根据右值的类型推断出左值的类型
// 因为简洁和灵活的特点,简短变量声明被广泛用于大部分的局部变量的声明和初始化
// 注意:由于使用了 := ,而不是赋值的 = ,因此推导声明写法的左值必须是没有被定义过的,若定义过,将会发生编译错误
name := "kuangshen"
age := 3
fmt.Printf("name:%s,age:%d",name,age)
  1. 打印变量类型和内存地址
fmt.Printf("%T,%T", name, age) 	// string,int
var num int = 5
fmt.Printf("num:%d的内存地址为:%p\n", num, &num) //num:5的内存地址为:0xc0000a6058
num = 100
fmt.Printf("num:%d的内存地址为:%p\n", num, &num) //num:100的内存地址为:0xc0000a6058
  1. 变量交换和匿名变量(类似于python)
var a int = 100
var b int = 200

b, a = a, b

a, _ = b, a
  1. 变量的作用域
    1. 局部变量
    2. 全局变量 ( 不包含这个全局变量的源文件需要使用"import"关键字引入全局变量所在的源文件之后才能使用这个全局变量。全局变量声明必须以var 关键字开头,如果想要在外部包中使用全局变量的首字母必须大写。 )
  2. 常量
const URL string = "192.168.1.1"	//显式定义
const URL2 = "192.168.1.1"			//隐式定义
const a, b, c = 3.14, "www.baidu.com", true		//同时定义

/*
iota,特殊常量,可以认为是一个可以被编译器修改的常量。iota是go语言的常量计数器
iota在const关键字出现时将被重置为0(const内部的第一行之前),const 中每新增一行常量声明将使iota计数一次(iota可理解为const语句块中的行索引)。

iota可以被用作枚举值:
*/
const (
		a = iota
		b = iota
		c = iota
	)
fmt.Println(a, b, c) // 0  1  2

const (
		a = iota
		b
		c
		d = "haha"
		e
		f = 100
		g
		h = iota
		i
	)
    const (
		j = iota
		k
	)
fmt.Println(a, b, c, d, e, f, g, h, i) // 0 1 2 haha haha 100 100 7 8 0 1  默认继承上一个元素的值


基本数据类型

在这里插入图片描述

布尔型

var flag bool = true

数字型

在这里插入图片描述

func main() {
	var i1 int8
	var i2 uint8

	i1, i2 = 100, 200
    
	fmt.Println(i1)
	fmt.Println(i2)

}
  • 浮点型,Go语言中默认是float64

在这里插入图片描述

  • 常见的别名

image.png

字符与字符串

字符时 rune(通用一点) 或者 byte

func main() {
    
	var str string
	str = "Hello,Go"
	fmt.Printf("%T,%s\n", str, str)

	v1 := 'A'
	v2 := "A"

	fmt.Printf("%T,%s\n", v1, v1)
	fmt.Printf("%T,%s\n", v2, v2)

}

/*
	string,Hello,Go
    int32,%!s(int32=65)//可以看到单引号定义的变量实际是int32类型,实际上打印的是对应ASCII表中的十进制值
    string,A 
*/
  • 部分用法
func main() {

	// 拼接
	fmt.Printf("aaa" + "bbb\n") // aaabbb    
	// 转义
	fmt.Printf("hello\"bbb\n") //	hello"bbb

    // 换行
	fmt.Printf("hello\nbbb") // hello \n bbb
    // Tab
	fmt.Printf("hello\tbbb") // hello  bbb
}
数据类型的装换

由于Go语言不存在隐式类型转换,因此所有的类型转换都必须显式的声明。

func main() {

	a := 3.14
	b := int(a)

	fmt.Println(a) // 3.14
	fmt.Println(b) // 3

}

运算符

  1. 算术运算符

image.png

  1. 关系运算符

在这里插入图片描述

  1. 逻辑运算符

image.png

  1. 位运算符

image.png

  1. 赋值运算符

image.png

流程控制

if
/*
 if 判断条件 {    //判断条件的括号可加可不加
  	满足条件执行的代码
 } else {
  	不满足执行的代码
 }
 */
switchfallthrough

switch语句的执行从上至下,直到找到匹配项,找到之后也不需要再加break,switch默认情况下case最后自带break语句。

package main

import "fmt"

func main() {

    score := 90

    switch score {
        case 90:
        	fmt.Println("A")
        	fallthrough    // fallthrough 会无视下一个case的条件,直接执行
        case 80:
        	fmt.Println("B")
        case 60,70:
        	fmt.Println("B")
        default:
        	fmt.Println("D)
     }

}

/*
 	A                                   
 	B  
*/

for
func main() {

    for i := 1; i <= 9; i++ {     //打印99乘法表
        for j := 1; j <= i; j++ {
            fmt.Printf("%d*%d=%d\t", j, i, j*i)
        }
        fmt.Println()
    }
}
2. 可以当做while语句使用
func main() {
	sum := 1
	for sum < 1000 {
		sum += sum
	}
	fmt.Println(sum)
}
brakecontinue
遍历字符串
package main

import "fmt"

func main() {

    score := 90
    name := "zhuwenjie"

    println(len(name))    // len(str) 获得字符串的长度

    fmt.Printf("%c,%d\n", name[1], name[1])

    for i := 0; i < len(name); i++ {
        fmt.Printf("%c,%d\n", name[i], name[i])
    }

    // i是下标,v是对应元素  类似于python的enum那个穷举类型
    for i, v := range name {   // for i, v := range name  其中i是下标,v是该下标对应的值
        fmt.Printf("%d,%c,%d\n", i, v, v)
    }

}

函数

声明

func function_name( [parameter list] ) [return_types] {
    函数体
}
1. 无参无返回值函数
func printInfo() {
    println("我执行了printInfo函数")
}

2. 有一个参数的函数
func printInfo(a int) {
    println(a)
}

3. 有两个参数的函数
func add(a int, b int) int {
    c := a + b
    return c
}

4. 有多个返回值的函数
c, d = addAndDel(a, b)
func addAndDel(a int, b int) (int, int) {
    c := a + b
    d := a - b
    return c, d
}

形参和实参

package main

func main() {
    // 形参与实参要一一对应,包括类型和顺序
    add, del := addAndDel(1, 2)
    println(add, del)
}

// addAndDel 计算两个数相加和相减的结果
// 形式参数: a b  定义函数时,用来接收外部传入数据的参数
// 实际参数: 1 2  调用函数时,传给形参的实际数据
func addAndDel(a int, b int) (int, int) {
    c := a + b
    d := a - b

    //一个函数在定义时如果有返回值,那么函数中必须使用return语句
    return c, d
}

可变参数

  • 如果一个函数的参数是可变参数,同时还有其他参数,可变参数要放在参数列表的最后
func myfunc(arg ...int){}

// arg ...int 告诉编译器这个函数接收不定数量的参数,类型全是int

package main

func main() {
    println(getSum(1, 3, 5, 7, 9))
}

func getSum(nums ...int) int {
    sum := 0
    for _, num := range nums {
        sum += num
    }
    return sum
}

参数传递

按照数据的存储特点来分:

  • 值类型的数据:操作的是数据本身,基础数据类型int、bool、array、struct…
  • 引用类型的数据:操作的是数据的地址,slice、map、chan…
值传递
package main

import "fmt"

func main() {

    //值传递  定义一个array数组  固定大小的
    arr := [4]int{1, 2, 3, 4}
    fmt.Println(arr)

    update(arr, 1, 100)
    fmt.Println(arr)

}

// 更改数组中某个元素的值
func update(arr [4]int, j int, target int) {
    arr[j] = target
    fmt.Println(arr)
}

/*
  [1 2 3 4] //未修改前数组的值
  [1 100 3 4] //update方法里修改后的值
  [1 2 3 4]  //修改后数组的值
*/

引用传递
package main

import "fmt"

func main() {

    //引用传递  定义一个arr切片  没写大小  说明可以变
    arr := []int{1, 2, 3, 4}
    fmt.Println(arr)

    update(arr, 1, 100)
    fmt.Println(arr)

}

// 更改切片中某个元素的值
func update(arr []int, j int, target int) {
    arr[j] = target
    fmt.Println(arr)
}

/*
  [1 2 3 4]  
  [1 100 3 4]
  [1 100 3 4]
*/

defer

defer语义:推迟、延迟
在Go语言中,使用defer关键字来延迟一个函数或者方法的执行。

package main

import "fmt"

func main() {

    f("1")
    fmt.Println("2")
    defer f("3")
    fmt.Println("4")

}

func f(s string) {
    fmt.Println(s)
}

/*
  1
  2
  4
  3
*/

defer函数或方法:该函数或方法的执行被延迟
如果一个函数中添加了多个defer语句,当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回。特别是当进行一些打开资源的操作时,遇到错误需要提前返回,在返回前需要关闭相应的资源,不然容易造成资源泄露问题。

  • 如果有很多调用defer,那么defer用的是后进先出(栈)模式。
  • 需要注意的是,在执行到defer语句的时候,函数里的形参就已经传递进去了,只是函数被延迟执行了。

常用场景:
对象.close() 临时文件的删除
文件.open
defer 文件.close
对文件进行操作

Go语言中关于异常的处理,使用panic()和recover()
    panic 函数用于引发恐慌,导致函数中断执行
    recover 函数用于恢复程序的执行,recover() 语法上要求必须在 defer 中执行

函数本质的探究

  1. 函数本身也是有数据类型的
func main() {
    fmt.Printf("%T", fs) 	// func()
}

func fs() {}
  1. 既然函数本身有数据类型,那么它就可以作为变量,可以赋值。
func main() {

    fmt.Printf("%T\n", fs) // func(int, int)

    //定义函数类型的变量
    var ff func(int, int) = fs
    ff(1, 2)  // 3   这一步等于 fs(1,2)

    //看看ff和fs是否相同
    fmt.Println(ff) //0x107fe40
    fmt.Println(fs) //0x107fe40

}

func fs(a int, b int) {
    fmt.Println(a + b)
}

匿名函数推导

func main() {

    // 函数正常执行
    f1()

    // 匿名函数就是没有名字的函数
    f2 := f1
    f2()

    // 匿名函数,函数体后增加一个()执行,通常只能执行一次
    func() {
        fmt.Println("我是一个匿名函数")
    }()

    // 将匿名函数赋值,单独进行调用
    f3 := func() {
        fmt.Println("我是一个匿名函数...")
    }
    f3()

    // 定义带参数的匿名函数
    func(a int, b int) {
        fmt.Println(a, b)
    }(1, 2)

    // 定义带返回值的匿名函数
    r1 := func(a int, b int) int {
        return a + b
    }(10, 20) //带了()就是函数调用
    fmt.Println(r1)

}

func f1() {
    fmt.Println("我是f1函数")
}

/*
  我是f1函数
  我是f1函数     
  我是一个匿名函数  
  我是一个匿名函数...
  1 2         
  30   
*/

回调函数

func main() {

    // 正常执行
    r1 := add(1, 2)
    fmt.Println(r1)

    // 封装
    r2 := oper(3, 4, add) //加
    fmt.Println(r2)

    r3 := oper(8, 4, sub) //减
    fmt.Println(r3)

    r4 := oper(8, 4, func(i int, i2 int) int { //乘
        return i * i2
    })
    fmt.Println(r4)

    r5 := oper(8, 4, func(i int, i2 int) int { //除
        if i2 == 0 {
            fmt.Println("除数不能为0")
            return 0
        }
        return i / i2
    })
    fmt.Println(r5)

}

// 高阶函数
func oper(a int, b int, fun func(int, int) int) int {
    r := fun(a, b)
    return r
}

func add(a int, b int) int {
    return a + b
}

func sub(a int, b int) int {
    return a - b
}

/*
  3
  7
  4
  32
  2
*/

闭包的理解

/*
  一个外层函数中,有内层函数,这个内层函数会操作外层函数的局部变量
  且该外层函数的返回值就是该内层函数
  这个内层函数和外层函数的局部变量,统称为闭包结构

  此时局部变量的声明周期就会发生变化,正常的局部变量会随着函数的调用而创建,随着函数的结束而销毁
  但是闭包中外层函数的局部变量并不会随着外层函数的结束而销毁,因为内层函数还在继续使用
*/
func main() {

    r1 := increment()
    fmt.Println(r1)

    fmt.Println(r1())

    v2 := r1()
    fmt.Println(v2)
    fmt.Println(r1())
    fmt.Println(r1())
    fmt.Println(r1())

    r2 := increment()
    fmt.Println(r2())

}

func increment() func() int {

    // 局部变量i
    i := 0

    // 定义一个匿名函数,给变量自增并返回
    fun := func() int {
        i++
        return i
    }

    return fun
}


/*
  0x8ae800
  1
  2
  3
  4
  5

  1
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

就你叫Martin?

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

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值