GO学习第一天 基础语法

学习仪式

package main

import "fmt"

func main() {
	fmt.Println("Hello World!")
    /* 我是注释 */
    // 我也是注释
}

  • 包声明:第一行代码 package main 定义了包名。你必须在源文件中非注释的第一行指明这个文件属于哪个包
  • 引入包:下一行 import "fmt" 告诉 Go 编译器这个程序需要使用 fmt 包
  • 函数:下一行 func main() 是程序开始执行的函数。main 函数是每一个可执行程序所必须包含的,一般来说都是在启动后第一个执行的函数
  • // 单行注释 ,/* */ 多行注释
  • Go 语言一行则是一个语句,不需要结尾写分号

标识符

就是给变量之类取名的东西,标识符可以由多个字母(A - Z,a-z)数字(1 - 9),下划线 _ 组成,但是第一个字符必须是字母或下划线而不能是数字。

例如无效标识符

  • 1ab (数字开头)
  • case (关键字)
  • a + b (表达式)

字符串连接

通过 + 进行连接

package main

import "fmt"

func main() {
   fmt.Println("你今天" + "真好看")
}

输出结果

你今天真好看

关键字或保留字

breakdefaultfuncinterfaceselect
casedefergomapstruct
chanelsegotopackageswitch
constfallthroughifrangetype
continueforimportreturnvar

除了以上介绍的这些关键字,Go 语言还有 36 个预定义标识符:

appendboolbytecapclosecomplexcomplex64complex128uint16
copyfalsefloat32float64imagintint8int16uint32
int32int64iotalenmakenewnilpanicuint64
printprintlnrealrecoverstringtrueuintuint8uintptr

程序一般由关键字、常量、变量、运算符、类型和函数组成。

空格

在 Go 的世界中,变量声明需要空格隔开

var name string

var age int

加入空格 也可以让代码更美观

result = a + b

格式化字符串

  • Sprintf 根据格式化参数生成格式化的字符串并返回该字符串。
  • Printf 根据格式化参数生成格式化的字符串并写入标准输出。
package main

import "fmt"

func main() {
   var money = 100
   var day = "2023-1-13"
   var str = "在%s这天我捡到了%d块钱"
   var target = fmt.Sprintf(str, day, money)
   fmt.Println(target)
}

输出结果

在2023-1-13这天我捡到了100块钱

数据类型

  • 布尔类型
    • true
    • false
  • 数字类型
    • int
    • float32
    • float64
  • 字符串类型
  • 派生类型
    • 指针类型
    • 数组类型
    • 结构化类型
    • Channel 类型
    • 函数类型
    • 切片类型
    • 接口类型
    • Map 类型

数字类型

序号类型和描述
1uint8 无符号 8 位整型 (0 到 255)
2uint16 无符号 16 位整型 (0 到 65535)
3uint32 无符号 32 位整型 (0 到 4294967295)
4uint64 无符号 64 位整型 (0 到 18446744073709551615)
5int8 有符号 8 位整型 (-128 到 127)
6int16 有符号 16 位整型 (-32768 到 32767)
7int32 有符号 32 位整型 (-2147483648 到 2147483647)
8int64 有符号 64 位整型 (-9223372036854775808 到 9223372036854775807)

浮点型

序号类型和描述
1float32 IEEE-754 32位浮点型数
2float64 IEEE-754 64位浮点型数
3complex64 32 位实数和虚数
4complex128 64 位实数和虚数

其他数字类型

序号类型和描述
1byte 类似 uint8
2rune 类似 int32
3uint 32 或 64 位
4int 与 uint 一样大小
5uintptr 无符号整型,用于存放一个指针

变量

声明变量一般使用 var 关键字:

var name string

var 变量名 类型

也可以一次声明多个变量

var name,phone string

package main

import "fmt"

func main() {
   var name, phone string
   name = "小明"
   phone = "8208208820"
   fmt.Println(name + "的电话号码是" + phone)
}

输出结果是

小明的电话号码是8208208820

如果变量声明时不赋值,那么就是默认的零值。

  • 数值类型(包括complex64/128)为 0
  • 布尔类型为 false
  • 字符串为 “”(空字符串)
  • 以下几种类型为 nil

    var a *int
    var a []int
    var a map[string] int
    var a chan int
    var a func(string) int
    var a error // error 是接口
    

声明方式

  • var
  • 自行判定
  • :=
package main

import "fmt"

func main() {
   // 手动指定类型
   var a int = 10
   // 自行判断
   var b = 10
   // :=
   c := 10
   fmt.Println(a, b, c)
}

结果

10 10 10

多变量声明

var 变量名1, 变量名2, 变量名3 类型
变量名1, 变量名2, 变量名3 = 值1, 值2, 值3

var 变量名1, 变量名2, 变量名3 = 值1, 值2, 值3

变量名1, 变量名2, 变量名3 := 值1, 值2, 值3

// 这种写法一般是全局变量
var (
	变量名1 类型1
	变量名2 类型2
)
package main

import "fmt"

/**
多变量声明
*/

var (
   x int
   y bool
)
var a, b int = 1, 2
var c, d = 3, 4

func main() {
   // := 只能在函数体内使用
   e, f := 5, 6
   fmt.Println(x, y, a, b, c, d, e, f)
}

输出结果

0 false 1 2 3 4 5 6

常量

常量是一个简单值的标识符,在程序运行时,不会被修改的量。

常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。

常量的定义格式:

const 常量名 类型 = 值

const LENGTH int = 100

package main

import "fmt"

// 常量

func main() {
	const LENGTH int = 100
	const WIDTH = 50
	var area int
	area = LENGTH * WIDTH
	fmt.Println("area is %d", area)
}

结果

area is %d 5000

还可以用作枚举

const (
	MAN = 0
	WOMAN = 1
)

也可以当做函数表达式

const (
   a1 = "hahah"
   b1 = len(a1)
   c1 = unsafe.Sizeof(a1)
)

数组

var 数组名[大小] 类型

var numbers [10] int

条件

if (条件) {
    表达式
}

循环

// 经典 for
for init; condition; post {
    
}
// 类似while
for condition {
    
}

Range

这种格式的循环可以对字符串、数组、切片等进行迭代输出元素。

for i, value := range values {
    
}

numbers := []int{1, 2, 3, 4, 5, 6}
for i, x := range numbers {
	fmt.Println(i, x)
}

函数

func function_name( [parameter list] ) [return_types] {
   
}
// 求两数最大值
func max(num1, num2 int) int {
   var result int
   if num1 > num2 {
      result = num1
   } else {
      result = num2
   }
   return result
}
// 返回多值
func swap(val1, val2 string) (string, string) {
   return val2, val1
}

指针

Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。

func main() {
	a := 10
	fmt.Println("变量地址%x", &a)
}

什么是指针

一个指针变量指向了一个值的内存地址。

类似于变量和常量,在使用指针前你需要声明指针。指针声明格式如下:

var 名称 *类型

package main

import "fmt"

func main() {
   var name string = "karl"
   var address *string // 声明指针变量

   address = &name
   fmt.Printf("address 指向的地址为 %x\n\n", address)
   fmt.Printf("name 地址为 %x\n\n", &name)
   fmt.Printf("adress指向的值为 %s\n\n", *address)
}

空指针

package main

import "fmt"

func main() {
   var ptr *int
   fmt.Printf("ptr value is : %x\n", ptr)

   if (ptr != nil) {
      fmt.Println("ptr 不是 空指针")
   } else {
      fmt.Println("ptr 是空指针")
   }
}

結果

ptr value is : 0
ptr 是空指针

结构体

声明:

type 结构体名字 struct {
    成员1 类型
    成员2 类型
    ...
}

使用

变量名 := 结构体名字{1,2,3...}
或者
变量名 := 结构体名字{成员1:1, 成员2:2, 成员3:3...}

访问

变量名.成员名

例:

type Person struct {
   name    string
   age     int
   address string
}
func main() {
	karl := Person{"karl", 18, "中国"}
	fmt.Println(karl)
}

// 访问成员
println(karl.age)

切片

// 声明
切片名 := make([]类型, 长度)
或者
var 切片名 []类型 


// 长度
len(切片名)


// 最长容量
cap(切片名)


// nil 切片
var numbers []int  // 不初始化 长度为0
if (number == nil)  -> true


// 截取
切片名[startIndex: endIndex]

// 追加
s = append(切片名, 追加元素)

// copy
append(目标切片, 原切片)

map

// 创建
var mapmap[key类型] value类型 // 默认是nil
or
map:= make(map[key类型] value类型)

// 增
map[key1] =1

//删
delete(map, key)
// 遍历
for key := range map{
    value = map[key]
}

类型转换

转换类型(原值)

接口

// 定义接口
type 接口名 interface {
    方法名1 返回类型1
    ...
}
// 定义结构体
type 结构体名 struct {
    
}

// 实现方法
func (结构体名 结构体) 接口方法名 {
    
}

// 使用
var 变量 接口名
变量.new(结构体)
变量.方法名
type Phone interface {
   call()
}

type HuaweiPhone struct {
}
type MiPhone struct {
}

func (huaweiPhone HuaweiPhone) call() {
   fmt.Println("我是华为手机")
}

func (miPhone MiPhone) call() {
   fmt.Println("我是小米手机")
}

func main() {
   var phone Phone
   phone = new(HuaweiPhone)
   phone.call()

   var miPhone Phone
   miPhone = new(MiPhone)
   miPhone.call()
}

错误处理

return errors.New(“错误信息”)

// a ÷ b
func divide(a, b float64) (float64, error) {
	if (b < 0) {
		return 0,errors.New("除 0 错误")
	}
	// code
}

Go并发

goroutine

go 函数名(参数列表)

// eg.
go f1(a, b, c)

// 开启一个新的goroutine
f1(a, b, c)
func say(s string) {
   for i := 0; i < 5; i++ {
      time.Sleep(10 * time.Millisecond)
      fmt.Println(s)
   }
}
func main() {
   go say("hi")
   go say("xi")
   say("aa")
}
// 结果
hi
xi
aa
aa
xi
hi
xi
aa
hi
aa
xi
hi
xi
aa

channel

通道(channel)是用来传递数据的一个数据结构。

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

ch <- v    // 把 v 发送到通道 ch
v := <-ch  // 从 ch 接收数据
           // 并把值赋给 v
func main() {
	s := []int{1, 2, 3, 4, 5, 6, 8, 9, 10}
	c := make(chan int)
	fmt.Println(len(s))
	go getSum(s[len(s)/2:], c)
	go getSum(s[:len(s)/2+1], c)
	a, b := <-c, <-c
	fmt.Println(a, b, a+b)
}
// 求和
func getSum(s []int, c chan int) {
	sum := 0
	for _, i := range s {
		sum += i
	}
	c <- sum
}

设置缓冲区大小

ch := make(chan int, 10)
	// 遍历
	ch := make(chan int, 2)
	ch <- 1
	ch <- 2
	println(<-ch)
	println(<-ch)
	// 关闭 在读数据时,如果管道中没有内容,将会发送堵塞。
	close(ch)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值