golang 基础语法和函数

文章目录

golang

golang语法

数据类型

类型 名称 长度 零值 说明
bool 布尔类型 1 false 其值不为真即为假,不可以用数字代表true或false
byte 字节型 1 0 uint8别名
rune 字符类型 4 0 专用于存储unicode编码,等价于uint32
int, uint 整型 4或8 0 有符号32位或无符号64位
int8 整型 1 0 -128 ~ 127,
uint8 整型 1 0 0 ~ 255
int16 整型 2 0 -32768 ~ 32767,
uint16 整型 2 0 0 ~ 65535
int32 整型 4 0 -2147483648 到 2147483647
uint32 整型 4 0 0 到 4294967295(42亿)
int64 整型 8 0 0 到 18446744073709551615(1844京)
uint64 整型 8 0 -9223372036854775808到 9223372036854775807
float32 浮点型 4 0.0 小数位精确到7位
float64 浮点型 8 0.0 小数位精确到15位
complex64 复数类型 8
complex128 复数类型 16 64 位实数和虚数
uintptr 整型 4或8 ⾜以存储指针的uint32或uint64整数
string 字符串 "" utf-8字符串

复制代码
+ go语言中不在提倡库的概念,都叫包
+ 同一个文件夹下面的包名必须一致
  • 在文件夹创建文件,默认包名和文件夹一致(也可以修改)

变量

Go语言引入了关键字var,而类型信息放在变量名之后

变量声明

  • 变量定义(要求定义的变量必须使用,如果不使用就会报错)

    • 最基础的 var 变量名 变量类型

    • 直接赋值的 var 变量名 = "string"

    • 第三种 ,直接推导类型 变量名 := 10

      :=只能在变量初次定义的时候使用,因为在这个时候系统会给变量申请空间

  • 多个变量一起定义

go 复制代码
var a,b,c,d,e int

变量赋值

go 复制代码
var a int = 10
var b int	= 20
var c,d int
c = 30
d = 40

fmt.Println(a,b,c,d)
  • 多个变量一起赋值
go 复制代码
  	a,b,c,d,_ := 1,2,3,4
 		a,d = d,a   //  值交换 
  • 要求变量的个数和值的个数必须保持一致

自动推导类型

go 复制代码
	a := 30
	fmt.Println(a)

匿名变量 其实就是-

示例:

go 复制代码
/*

*/
//默认的包名
package main
//导入包

import "fmt"


func main()
{
    //go 语言中定义变量, 在go语言中定义了变量就必须使用
    //1 先定义变量,在赋值
    var a int;
    a = 10;
    //2 直接赋值
    var b = "string";
    
    //3 自动推导类型 := 只能在变量定义的时候使用
    c:= true;
    
    /*
    	var d := 3.14; 
    	这种定义是错误的,因为在var 会申请空间, := 也会申请空间
    */
   
    fmt.Println("hello world!" , a, b, c);    
}

//直接执行
$ go run test.go
hello world!

//直接执行
$ go run test.go
hello world! 10

//先编译
$ go build test.go
//在执行
$./test
hello world! 10 string

$ go run test.go
hello world! 10 string true

函数

  • 普通函数
  • 不定参函数

函数的基本格式

在 Go 语言中,函数使用 func 关键字定义,基本语法如下:

go 复制代码
func 函数名(参数列表) (返回值列表) {
    // 函数体
}
1. 普通函数定义
  • 函数名:遵循标识符命名规则,首字母大写表示包外可导出(public),小写表示包内私有(private)。
  • 参数列表:多个参数用逗号分隔,类型写在参数名后面。如果相邻参数类型相同,可以省略前面参数的类型声明。
  • 返回值列表 :可以返回零个、一个或多个值。多个返回值需要用括号 () 括起来。

示例:

go 复制代码
// 无参数无返回值
func SayHello() {
    fmt.Println("Hello, World!")
}

// 带参数无返回值
func PrintSum(a int, b int) {
    fmt.Println(a + b)
}

// 参数类型相同可简写
func PrintSum2(a, b int) {
    fmt.Println(a + b)
}

// 单个返回值
func Add(a, b int) int {
    return a + b
}

// 多个返回值(匿名返回)
func Divide(a, b int) (int, int) {
    quotient := a / b
    remainder := a % b
    return quotient, remainder
}

// 多个返回值(有名返回)
func DivideNamed(a, b int) (q int, r int) {
    q = a / b
    r = a % b
    return // 直接 return,q 和 r 已被赋值
}
2. 不定长参数(Variadic Functions)

Go 支持不定长参数,使用 ... 语法,表示该参数可以接收任意数量的同类型值。不定长参数必须是参数列表中的最后一个参数。

示例:

go 复制代码
// 不定长参数示例
func Sum(numbers ...int) int {
    total := 0
    for _, num := range numbers {
        total += num
    }
    return total
}

func PrintInfo(name string, scores ...int) {
    fmt.Printf("Name: %s\n", name)
    fmt.Printf("Scores: %v\n", scores)
}

func main() {
    fmt.Println(Sum(1, 2, 3, 4, 5))        // 输出: 15
    fmt.Println(Sum())                      // 输出: 0,不定参可以是0个
    PrintInfo("Alice", 90, 85, 95)
}

在函数内部,不定长参数被当作切片(slice)处理,可以通过 range 遍历。

3. 返回值详解

Go 函数的返回值有两种形式:匿名返回有名返回

  • 匿名返回 :在函数签名中只声明返回类型,不指定变量名。函数体内使用 return 语句显式返回具体值。
  • 有名返回 :在函数签名中为返回值指定变量名。这些变量在函数开始时被初始化为其零值,在函数体内可以直接使用。return 语句可以不带参数,此时返回当前有名变量的值。

注意:

  1. 如果函数有多个返回值,要么全部使用匿名返回,要么全部使用有名返回,不能混用。
  2. 有名返回时,return 后面可以跟值,此时返回值变量的值会被覆盖。
  3. 有名返回时,return 后面可以不跟任何值,此时返回当前已赋值的返回值变量。

示例对比:

go 复制代码
// 匿名返回
func GetCoordinates() (float64, float64) {
    x := 10.5
    y := 20.3
    return x, y
}

// 有名返回
func GetCoordinatesNamed() (x float64, y float64) {
    x = 10.5
    y = 20.3
    return // 等价于 return x, y
}

// 有名返回,return 带值会覆盖
func GetCoordinatesOverride() (x float64, y float64) {
    x = 10.5
    y = 20.3
    return 30.0, 40.0 // x 和 y 的值被覆盖,最终返回 (30.0, 40.0)
}
4. defer 延迟调用

defer 语句用于延迟函数的执行,直到包含它的函数返回。defer 通常用于资源清理(如关闭文件、解锁互斥锁)或确保某些操作在函数结束时执行。

特性:

  1. defer 后面的语句会在函数返回之前执行。
  2. 一个函数中可以有多个 defer 语句,它们以 栈(LIFO,后进先出) 的顺序执行。
  3. defer 可以跟函数调用或匿名函数。
  4. defer 语句中的参数会在 defer 语句执行时立即求值,但函数调用会延迟。

示例:

go 复制代码
func TestDefer() {
    defer fmt.Println("defer 1: 最后执行")
    defer fmt.Println("defer 2: 倒数第二执行")
    fmt.Println("正常执行: 最先执行")
}
// 输出:
// 正常执行: 最先执行
// defer 2: 倒数第二执行
// defer 1: 最后执行

// defer 用于资源清理
func ReadFile(filename string) (string, error) {
    file, err := os.Open(filename)
    if err != nil {
        return "", err
    }
    defer file.Close() // 确保函数返回前关闭文件
    
    content, err := io.ReadAll(file)
    if err != nil {
        return "", err
    }
    return string(content), nil
}

// defer 参数立即求值示例
func DeferEvaluation() {
    i := 0
    defer fmt.Println("defer i =", i) // i 的值此时是 0
    i++
    fmt.Println("normal i =", i)      // i 的值现在是 1
}
// 输出:
// normal i = 1
// defer i = 0
5. 函数调用与可见性
  • 包内调用:同一个包内的函数,无论首字母大小写,都可以直接调用。
  • 跨包调用:只有首字母大写的函数(公开函数)才能被其他包调用。
  • main 包特殊 :在 main 包中,如果多个文件属于同一个包,它们之间的函数调用需要编译时指定所有相关文件。

总结: Go 的函数设计简洁而强大,支持多返回值、不定长参数、延迟执行等特性,结合严格的可见性规则,使得代码模块化清晰,易于维护。### 函数的返回值

  • 注意,如果返回值有多个,是匿名返回的话就都必须是匿名返回,如果是有名返回的话就都必须是名返回
  • 如果返回值中return后面跟有确定的值,那么当有名返回的时候,值会被覆盖
  • 如果有名返回的话,return后可以不跟任何值(会被覆盖)
  • defer延迟调用 在函数结束的时候调用defer后面的语句,语句只能有一条
  • defer的执行顺序在一个函数内是栈结构,是先进后出 ,在return函数后面语句执行完之后然后执行defer的语句
  • defer后面可以跟函数调用,也可以跟匿名函数
go 复制代码
//有名返回值
func Test(a, b int)(r sring){
    
    defer fmt.Println("33333")	//先进后出 
    defer fmt.Println("22222")	
    defer fmt.Println("11111")	
    
    fmt.Println("hello")
	r = a+b
	return r
}

//匿名返回
func MyFunc(a int)(int,int){
    
}

功能管理

可以通过go env命令来查看go有关的环境

goroot

存放go语言的源码,还会存放Go语言的标准库 /usr/local/go

gopath

非常重要的命令是go get github.com/

放置go get下载的内容,同时也放扩展

go run /go build的时候go语言会在这两个目录下面找你导入的包,如果找不到,就会提示错误

所以我们一般创建的项目都放在gopath中

跨包的使用

  • 当存在跨包之间调用的时候,函数或者变量首字母都需要大写
  • 当在main包中,存在互相调用的情况,在编译或者是执行的时候,都需要手动指定调用的函数所在的文件
  • _的作用,第一个是调用包担不使用包,第二个作用是会调用包中的init函数
相关推荐
渡我白衣1 小时前
定时器与时间轮思想
linux·开发语言·前端·c++·人工智能·深度学习·神经网络
luyun0202021 小时前
实用小工具,吾爱出品
开发语言·c++·算法
Highcharts.js1 小时前
Highcharts React v5版本迁移的核心注意事项和步骤清单
开发语言·javascript·react.js·前端框架·highcharts
轻刀快马1 小时前
浅聊Java反射
java·开发语言
Gerardisite1 小时前
企业微信智能客服开发实战:API自动回复指南
java·开发语言·python·机器人·企业微信
智塑未来1 小时前
装备制造行业设计制造一体化痛点攻克与实战经验总结
java·开发语言·制造
Shadow(⊙o⊙)1 小时前
硬核手搓解析!进程-内核分析:命令行参数及环境变量,重构main()
linux·运维·服务器·开发语言·c++·后端·学习
StackNoOverflow1 小时前
RabbitMQ 入门详解(含安装 + 配置 + 管理后台)
开发语言·后端·ruby