Go语言学习笔记----基本语法与使用

变量

  1. 变量声明的基本样式
var a int //整型类型
var  b string //字符串类型
var c []float32 //声明32位浮点切片类型,表示由多个浮点类型组成
var d func() bool //返回值为布尔类型的函数变量
var e struct{
	x int
}//结构体类型变量,拥有一个整型x字段

也可以使用批量格式(专为懒癌患者定制)

var{
 a int
 b string 
 c []float32
 ...
}
  1. 初始化变量
    Go语言在声明变量时,自动对变量对应的内存区域进行初始化操作。每个变量会初始化其类型默认值。如

整形和浮点型变量默认值是0
字符串型变量默认值是空字符串
布尔型变量默认值是false
切片,函数,指针默认值是nil

初始化标准格式:

var hp int =100

短变量声明并初始化

var hp int //声明hp变量
hp :=10

短变量声明并初始化格式在开发中使用比较普遍。

  1. 多个变量同时赋值
    使用Go语言的多重赋值的特性可以轻松完成交换任务。如:

var a int =100
var b int =200
b,a=a,b //进行交换

多重赋值时,变量的左值和右值按从左到右的顺序赋值。
应用:多重赋值在GO语言的错误处理和函数返回值中会大量的使用。

  1. 匿名变量—没有名字的变量
    在使用多重赋值时,如果不需要在左值中接收变量,可以使用匿名变量。表现是用一个"_"下划线,使用匿名变量时,只需要在变量声明的地方使用下划线代替。
func GetData(int,int){
return 100,200
}

a,_:=GetData()
_,b :=GetData()

数据类型

在上一次笔记中粗浅了解过。

基本数据类型有:整型、浮点型、布尔型、字符串、切片、指针、结构体,函数,map,通道。
切片有类似指针的便利性,但比指针更安全。
结构体是Go语言的复杂类型之一
函数类型,作用是可以对其进行赋值和获取。
map和切片是开发中的常见数据容器类型。

整型,浮点型,布尔型都很熟悉不做介绍。简单介绍后几种的一些类型。

1.字符串
1.1计算字符串长度
内建函数len(),可以用来获取切片、字符串、通道等的长度。

tip1 := “genji is a ninja”
fmt.Println(len(tip1))

程序输出16

1.2.遍历字符串-----获取每一个字符串元素
有两种方法:
(1)遍历每一个ASCII字符

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

(2)按Unicode字符遍历字符串

theme :="狙击 start"
for _,s :=range theme{
	fmt.Printf("Unicode: %c\n",s)
}

1.3.获取字符串的某一段字符
我们使用strings.Index()函数在字符串中搜索另一个子串,代码如下:

tracer :="死神来了, 死神bye bye"
comma :=strings.Index(tracer,",")//计算,的位置,值为12
pos :=strings.Index(tarcer[comma:],"死神")计算死神这个字符出现的位置,值为3
fmt.Println(comma,pos,tracer[comma+pos:])

结果为12 3 死神bye bye

注意:comma的结果为12,因为Go语言中文为UTF-8编码,每个中文占3个字节。

1.4.修改字符串
Go语言的字符串无法直接修改每一个字符元素,只能通过重新构造新的字符串并赋值给原来的字符串变量实现。

angel :="Heros never die"
angleBytes :=[]byte(angel)
for i:=5;i<=10;i++{
	angelBytes[i]=' '
}
fmt.Println(string(angleBytes))

输出为 Heros die

总结:

  • Go语言的字符串是不可变的。
  • 修改字符串时,可以将字符串转换成[]byte进行修改
  • []byte和string可以通过强制类型转换互换

1.5.连接字符串
Go语言和大多数语言一样,使用"+"对字符串进行连接操作。但不高效。它还可以使用类似StringBulid的方法进行高效连接。例如:

hammer :="吃我一锤"
sickle :="死吧"
//声明字节缓冲
var stringBuilder bytes.Buffer//bytes.Buffer是可以缓冲并可以往里面写入各种字节数组的

//把字符写入缓冲
stringBuilder.WriteString(hammer)
stringBulider.WriteString(sickle)

//将缓冲以字符串形式输出
fmt.Println(stringBuilder.String())//用stringBuilder.String()将缓冲转换成字符串

1.6.格式化
格式化函数写法:

fmt.Sprintf(格式化样式,参数列表)

三种不同的格式输出:

1//两参数格式化,与c语言相似
var progress=2
var target=8
title :=fmt.Sprintf("已采集%d个药草,还需要完成%d个任务",progress,target)

输出:已采集2个药草,还需要完成8个任务
(2)
//按数值本身输出
pi :=3.1415926
variant=fmt.Sprintf("%v %v %v",月球基地,pi,true)

输出:月球基地,3.1415926true
(3)
//匿名结构体声明,并赋予初值
profile :=&struct{
Name string
HP  int
}
{
Name: "rat",
HP:   "150",
}
fmt.Printf("使用‘%%+v’ %+v\n",profile)
输出:使用%+v, &{Name:rat HP:150}
fmt.Printf("使用'%%#v' %#v\n",profile)
输出:使用%#v &struct {Name String; HP int}  {Name:rat HP:150}
fmt.Printf("使用'%%T' %T\n",profile)
输出:使用%T *struct {Name String; HP int}

常用动词及功能

动词 功能
%v 按本来值输出
%+v 在%v基础上,对结构体字段名和值进行展开
%#v 输出Go语言语法格式的值
%T 输出Go语言语法格式的类型和值
%p 指针,十六进制方式显示
%% 显示%本体

2.切片
切片是一个拥有相同类型元素的可变长度的序列,能动态分配空间。声明如下:

var name []T

示例:

a :=make([]int,3)
a[0]=1
a[1]=2
a[2]=3

创建一个容量为3的整形切片,并为元素赋值。
切片还可以在其元素集合内连续地选取一段区域为新的切片,就像其名字“切片”一样,切出一块区域,形成新的切片。
如:

str :="hello world"
fmt.Println(str[6:])

输出world.

  1. 指针
    指针概念在go语言中被拆分为两个核心概念。
  • 类型指针:允许这个指针类型的数据进行修改。传递数据使用指针,而无须拷贝数据。类型指针不能进行偏移和运算
  • 切片,由指向起始元素的原始指针、元素数量和容量组成。

Go语言的指针类型变量拥有指针的高效访问,但又不会发生指针偏移,从而避免非法修改关键性数据问题。同时,垃圾回收也比较容易对不会发生偏移的指针进行检索和回收。

注意:切片比原始指针具备更大的特性,更为安全。切片发生越界时,运行时会报出宕机,并打出堆栈,而原始指针只会崩溃。

指针地址和指针类型:
Go语言中使用"&"操作符放在变量前面对变量进行"取地址"操作。

ptr := &v //v的类型为T
v代表被取地址的变量,被取地址的v使用ptr变量进行接收,ptr的类型就为"T",称作T的指针类型。""代表指针。

取值操作,用"*"进行取值,如

value := *ptr

使用指针修改值,前面已经说过使用多重赋值的方法进行数值交换,使用指针同样可以进行数值交换。代码如下:

//交换函数
func swap(a,b,*int){
	t := *a
	*a = *b
	*b =t
}

和c语言非常相似。而且Go语言函数中如果只是交换两个指针值的话,在主函数中是交换不成功的。如:

func swap(a,b,*int){
	b,a=a,b
}

创建指针的另一种方法-----new()函数

str := new(string)//new()函数可以创建一个对应类型的指针,创建过程会分配内存
*str ="ninjia"

4.常量----恒定不变的值
定义常量:

const pi=3.1415926
const e =2.71856

或者多组一起定义

const(
pi=3.1415926
e =2.71856
)

5.枚举-----一组常量值
Go语言没有枚举类型,但是有iota可以模拟枚举

type Weapon int
const(
Arrow Weapon =iota//开始生成枚举值,初始为0,之后自动增加1枚举值
Shuriken
SniperRifle 
Rifle
Blower
)

例子:用iota实现KB,MB,GB的自动递增。

package main

import (
	"fmt"
)

const (
	B float64 = 1 << (iota * 10)
	KB
	MB
	GB
	TB
)

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

输出1024

6.类型别名
类型别名是Go 1.9版本新功能。主要用于代码升级、迁移中类型的兼容性问题。在C/C++中,重构升级可以使用宏快速定义新的一段代码。Go语言中没有选择加入宏,而是将解决重构中最麻烦的类型名变更问题
版本1.9之前的内建类型定义的代码是这样写的:

type byte uint8
type rune int32

版本1.9之后是这样的,这个修改就是配合类型别名进行的修改。

type byte = uint8
type rune = int32

区别类型别名和类型定义
类型别名写法:

type TypeAlias = int //给int取别名为TypeAlias

类型定义写法:

type NewInt int //将NewInt定义为int类型

区别在于:
类型别名只是类型的一个另外的名字,比如一个孩子有英文名,有小名,本质上是同一个类型。
类型定义是定义NewInt为int类型,具备int的特性,Newint将成为一种新的类型。

上面的定义如果用代码进行类型判断如:

var a NewInt
fmt.println("a type is:%T\n",a)
var a2 TypeAlias
fmt.println("a2 type is:%T\n",a2)

输出将是:

a type is: NewInt
a2 type is: int

发布了40 篇原创文章 · 获赞 23 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/suoyudong/article/details/104874667