基本语法

源文件构成

最简单的一个go程序:

package main

import "fmt"

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

Go源程序由几部分构成:

  1. package用于包声明:package main表示一个可独立执行的程序,** Go应用程序必须包含名为main的包**,如果无main包,那么编译器会提示"cannot run non-main package";
  2. import用于导入需要引用的外部包, import "fmt"告诉 Go 编译器这个程序需要使用 fmt 包;
  3. func main()是程序的主函数,一般来说都是在启动后第一个执行的函数(如果有init() 函数则会先执行init函数);
  4. 标识符由字母、数字和下划线构成,首字符必须是字母或者下划线,Go语言通过标识符的首字母标识是否可以导出到外部:
  • 当标识符以大写字母开头,那么这个标识符就可以被外部包引用,也称为导出,类似于面向对象语言中的public
  • 当标识符以小写字母开头,则对包外是不可见的,类似于面向对象语言中的protected

数据类型

变量分为值类型和引用类型:

  • 值类型:int、float、bool 和 string 这些基本类型都属于值类型,使用这些类型的变量直接指向内存中的值;
  • 引用类型:引用类型的变量保存的是被引用对象的地址,也就是C语言中的指针。

基本类型变量

Go语言中的变量类型基本涵盖了C语言的基本类型,同时增加指定长度的类型,例如:int8、uint8、int16、uint16、int32、uint32等。

Go语言中有多种定义变量的方法,分别介绍:

  1. 定义变量时指定数据类型,格式var v_name v_type,范例:
var varInPackage1 int			// 本地变量,没有赋初始值
var varInPackage2 int = 10 // 本地变量赋初始值为10
var VarInPackage int = 20 // 全局变量赋初始值为20
  1. 省略类型,让编译器根据右值推测数据类型:
var intVar = 10
var stringVar = "String"
  1. 省略var关键字,通过:=进行赋值,这种定义只能位于函数体内,用于创建局部变量,所以必须确保变量没有被定义过:
intVar := 10
intVar1, strVar = 20, "StrValue" // 同时定义两个变量
a, _ = 10, 20 // 忽略第二个参数
  1. 因式分解方式,一般用于声明全局变量:
var (
a int
b bool
)

go语言中变量的作用域与C语言相同。

数组

数组的定义:

var variable_name [SIZE] variable_type

创建数组格式:

var balance1 [10] int32 // 创建一个容量为10的数组
var balance2 = [5]float32{1.0, 2.0, 3.4, 7.0, 5.1} // 创建一个容量为5的数组,并且赋初始值
var balance3 = [...]float32{1.0, 2.1, 3.4, 7.5, 5.0} // 创建一个数组容量由后面定义的数据决定

切片

切片(slice)是对数组一个连续片段的引用(该数组我们称之为相关数组,通常是匿名的),所以切片是一个引用类型,切记不可用指针指向切片!!

和数组不同的是,切片的长度可以在运行时修改,最小为 0 最大为相关数组的长度:切片是一个 长度可变的数组

切片的声明格式:

var identifier []type 	// 注意方括号为空

创建切片

切片有几种创建方法:

  1. 与特定数组绑定,创建方法为:
var slice1 []type = arr1[start:end]  // arr1为已经创建的数组或者切片
  1. 直接创建切片:
var x = []int{2, 3, 5, 7, 11}	// 创建一个长度为5的切片
  1. 使用make创建切片:
slice1 := make([]type, len)			// len为切片的初始长度
slice1 := make([]type, len, cap) // cap为切片初始容量

调整容量

切片可以调整容量,下面的代码用于将sl的容量增加1:

sl = sl[0:len(sl)+1]

下面的将去掉切片的第一个元素:

sl = sl[1:len(sl)]

字符串与切片

Go语言中字符串是常量,不可变。

如果需要修改字符串中的某个数字,则需要将字符串转化成切片后再进行修改。

例如,将字符串 "hello" 转换为 "cello":

s := "hello"
c := []byte(s)
c[0] = 'c'
s2 := string(c) // s2 == "cello"

常量

通过const关键字创建常量,常量的定义方法与变量类似,差异在于将var替换为const,范例:

const a string = "abc"
const b = "abc"

下面介绍一个特殊的常量iota,可以认为这个是在编译前进由编译器修改的常量。

在一个const组中,首次使用iota时值为0,每使用一次,iota自动加一,这种用法一般作为enum类型使用:

const (
a = iota // 首次调用,所以a=0
b // 不赋任何值时,就是使用与上一个变量相同的方式赋值,所以这个等价于 b = iota,即使不写iota,编译器默认就是自动调用
c // 等价于 c = iota
) const (
a1 = iota // 这是一个新的const组,iota初始值为0,所以a1=0
a2 // 等价于 a2 = iota
)

String

Go语言提供了strings包,专门处理string类型的数据。

例如:

  • strings.Contains()判断字符串中是否包含特定字符串;
  • strings.Index()返回特定字符串在指定字符串中的位置;
  • ...

文档可以参考:https://studygolang.com/pkgdoc

Map

Map 是一种无序的键值对的集合,Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。

Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它,但是Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。

map声明方式:

var map_variable map[key_data_type]value_data_type

map 是 引用类型 的: 内存用 make 方法来分配,最简单的初始化:

var map1 = make(map[keytype]valuetype)
var map1 = make(map[keytype]valuetype, cap) // 指定容量

也可以带初始值方式创建,例如:

mapCreated := map[string]float32{"C0": 16.35, "D0": 18.35}

范例:

var kvs = make(map[string]string)	// 创建一个Map

kvs["AAA"] = "aaa";
kvs["BBB"] = "bbb"; for k,v := range kvs { // 遍历Map
fmt.Printf("\tK=%s, V=%s\n", k, v)
} v,ret := kvs["CCC"] // 查找map,第一个返回值是key对应的value,第二个返回值是结果
fmt.Printf("\tfind CCC, ret=%d, v=%s\n", ret, v)

控制

条件语句

if

if语句格式与C语言相比,只不过测试表达式不带括号(也可以带括号),其他与C语言相同:

if 测试表达式 {
/* 在布尔表达式为 true 时执行 */
} else {
/* 在布尔表达式为 false 时执行 */
}

switch

Go的switch与C的类似,与C的差异在于默认每个case后面自带break语句,如果不需要break,则需要通过fallthrough关键字指明。

范例:

switch marks {
case 90:
grade = "A"
case 80:
grade = "B"
case 50,60,70 :
grade = "C"
fallthrough // 表示没有break,相当于接着执行default里面的语句
default:
grade = "D"
}

ifswitch还有另外一种写法,支持接受一个初始化参数,格式如下:

if initstatement; condition {}
switch initstatement; condition {}

例如:

if err := file.Chmod(0664); err != nil

循环语句

循环控制:

for init; condition; post { }	// 与C语言相同
for condition { } // 等同于 while(condition)
for { } // 等同于 for(;;)

for循环的init/post段不支持通过,分隔多个表达式,如果您需要初始化多个变量时,可以通过下面的方式:

sum := 0
for i,j := 0,100; i<=j; i++ {
sum += i
}

循环遍历array、slice、string、map时,可以使用range关键字进行控制,range第一个参数返回的是索引,第二个参数返回的是该索引位置的值:

strings := [] string{"string1", "string2", "string last"}
for i,s :=range strings {
fmt.Printf("\t%d = %s\n", i, s)
}

函数

函数定义

标准函数定义如下:

func function_name([parameter list]) [return_types] {
函数体
}

函数的参数同C语言一样,存在值传递和引用传递,引用传递的方式与C语言的指针格式相同:

func swap(x *int, y *int) {
var temp int
temp = *x /* 保持 x 地址上的值 */
*x = *y /* 将 y 值赋给 x */
*y = temp /* 将 temp 值赋给 y */
}

而实际上如果进行swap,还有更简单的方式,例如下面是调换a、b两个变量的值:

a, b = b, a

函数变量

C语言中一般使用函数指针来指向一个函数,Go中可以直接将将函数赋值给变量,该变量就是函数:

// 创建一个函数变量 getSquareRoot
getSquareRoot := func(x float64) float64 {
return math.Sqrt(x)
} fmt.Println(getSquareRoot(9)) /* 使用函数 */

闭包

所谓闭包,就是将函数自身使用的数据封装到包中,对外不可见。

参考下面的函数,getSequence函数返回一个函数,被返回的函数中引用了getSequence函数的一个局部变量,所以只要被返回的函数存在,那么getSequence函中的局部变量i就会存在,这个就是相当于将i变量封到了包中,即闭包。

func getSequence() func() int {
i:=0
return func() int {
i+=1 // 这里可以引用getSequence函数中定义的局部变量
return i
}
} nextNumber := getSequence() // 创建闭包

多值返回

Go语言中一个函数可以返回一个或者多个值,多值返回函数范例:

func swap(x, y string) (string, string) {
return y, x
}

也可以对返回值参数进行命名,这样就可以在函数体中对返回值参数进行赋值,这个赋值就是相当于设置返回值,范例:

func f(x, y int) (sum int, sub int) {
sum = x+y
sub = x-y
return
}

defer

关键字defer允许我们推迟到函数返回之前执行,如果一个函数存在多个defer语句,那么按照后进先出的顺序执行,即栈的顺序。

例如,下面的代码指定了2个Defer:

func deferFunc() {
fmt.Printf("Hello here is defer funtion\n");
} func testDeferFunc() {
fmt.Printf("print 1\n")
defer deferFunc()
defer func() { // 创建一个匿名函数,并defer执行
fmt.Printf("Hello here is defer function, inner\n")
}()
fmt.Printf("print 2\n")
}

输出结果为:

print 1
print 2
Hello here is defer function, inner
Hello here is defer funtion

Go语言学习:01-基本语法的更多相关文章

  1. C语言学习-01第一个C语言程序

    一 C语言的历史 C语言是一门通用计算机编程语言,应用广泛.C语言的设计目标是提供一种能以简易的方式编译.处理低级存储器.产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言. 尽管C语言提供 ...

  2. Groovy语言学习--语法基础(5)

    至此groovy语言学习-语法基础就结束了,新的工作已经安排下来,要干活了. 对groovy了解到一定程度之后就可以在java项目中对其进行引入了.为此新建了一个微型的项目,个人觉得千言万语不如代码实 ...

  3. Groovy语言学习--语法基础(1)

    2018年11月末,从上家公司离职后进入现在的公司.进入项目以来,发现项目中有很多groovy脚本,以前没接触过groovy,抽时间系统地学一下,也方便后期项目的开发和维护. groovy和java的 ...

  4. Python学习--01入门

    Python学习--01入门 Python是一种解释型.面向对象.动态数据类型的高级程序设计语言.和PHP一样,它是后端开发语言. 如果有C语言.PHP语言.JAVA语言等其中一种语言的基础,学习Py ...

  5. 郝斌老师C语言学习笔记(一)

    在给变量分配内存时,很可能这段内存存在以前其他程序使用留下的值.当使用VC编译器,若编译器发现没有给变量赋值而使用,就会返回一个以“85”开头的很大的数字(此时该段内存中为一个垃圾数,为了避免出现较常 ...

  6. 01 C语言程序设计--01 C语言基础--第1章 C语言概述&第2章 GCC和GDB

    走进嵌入式开发的世界,企业级项目课程让你达到企业嵌入式应用开发要求.名师在线答疑,解决疑难.科学评测体系,系统评估学习.核心项目实........ 30 门课程 241小时12分钟 824 人学习 学 ...

  7. 【转】朱兆祺教你如何攻破C语言学习、笔试与机试的难点(连载)

    原文网址:http://bbs.elecfans.com/jishu_354666_1_1.html 再过1个月又是一年应届毕业生应聘的高峰期了,为了方便应届毕业生应聘,笔者将大学四年C语言知识及去年 ...

  8. Java语言学习day02--6月29日

    Java语言学习day02###01常用的DOS命令 * A: 常用的DOS命令 * a: 打开Dos控制台 * win+r--cmd--回车 * b: 常用dos命令 * cd.. : 退回到上一级 ...

  9. HTML语言学习笔记(会更新)

    # HTML语言学习笔记(会更新) 一个html文件是由一系列的元素和标签组成的. 标签: 1.<html></html> 表示该文件为超文本标记语言(HTML)编写的.成对出 ...

  10. linux 下C语言学习路线

    UNIX/Linux下C语言的学习路线.一.工具篇“公欲善其事,必先利其器”.编程是一门实践性很强的工作,在你以后的学习或工作中,你将常常会与以下工具打交道, 下面列出学习C语言编程常常用到的软件和工 ...

随机推荐

  1. c++nullptr(空指针常量)、constexpr(常量表达式)

    总述     又来更新了,今天带来的是nullptr空指针常量.constexpr(常量表达式)C++的两个用法.Result result_fun = nullptr;constexpr stati ...

  2. 16天5面,我终于拿到了鹅厂Offer

    目录 1 - 为什么要在年底离职 1.1 惊觉:没有什么成长 1.2 投简历,敲打自己 1.3 面试它来了 1.4 提前触到目标? 2 - 我的鹅厂面试 2.1 技术一面 Java 语言相关 通用学科 ...

  3. 2019牛客暑期多校训练营(第三场)A.Graph Games (分块)

    题意:给你n个点 m条边的一张图 现在有q次操作 每次操作可以选择反转l~r的边号 也可以询问S(l)和S(r) 连接成的点集是否相同 思路:我们把m条边分块 用一个S数组维护每块对一个点的贡献 然后 ...

  4. BZOJ1396 识别子串【SAM+SegmentTree】

    BZOJ1396 识别子串 给定一个串\(s\),对于串中的每个位置,输出经过这个位置且只在\(s\)中出现一次的子串的最短长度 朴素的想法是,我们要找到那些只出现一次的子串,之后遍历每个串,把串所覆 ...

  5. 头疼的Python 脚本报错

    Python 脚本报错 检查是否用了制表符.变量声明前面不能用制表符,只能用空格,版本为2.7.14

  6. 记一次基于springboot+aop实现日志记录实战

    1. 为什么要记录日志 好处: a. 可以对一些重要功能进行记录,方便以后跟踪是谁操作此功能的. b. 在操作某些功能时可能会发生异常,但每次出现异常我们想定位日志都要去服务器查看我们的日志.有了日志 ...

  7. codeforces 1076E Vasya and a Tree 【dfs+树状数组】

    题目:戳这里 题意:给定有n个点的一棵树,顶点1为根.m次操作,每次都把以v为根,深度dep以内的子树中所有的顶点(包括v本身)加x.求出最后每个点的值为多少. 解题思路:考虑到每次都只对点及其子树操 ...

  8. Spring(二) Mini版Spring的实现

    实现思路 先来介绍一下 Mini 版本的 Spring 基本实现思路,如下图所示: 自定义配置 配置 application.properties 文件 为了解析方便,我们用 application. ...

  9. java有序数组的有序交集

    public static void main(String[] args) throws ParseException { int[] a = {4,5,-1,-1}; int[] b = {-1, ...

  10. 云原生系列2 部署你的第一个k8s应用

    云原生的概念和理论体系非常的完备,but talk is cheap , show me the code ! 但是作为一名程序员,能动手的咱绝对不多BB,虽然talk并不cheap , 能跟不同层次 ...