GO语言系列(二)- 基本数据类型和操作符
一、文件名 & 关键字 & 标识符
1.所有go源码以.go结尾
2.标识符以字母或下划线开头,大小写敏感
3._是特殊标识符,用来忽略结果
4.保留关键字
除了以上介绍的这些关键字,Go 语言还有 36 个预定义标识符:
append | bool | byte | cap | close | complex | complex64 | complex128 | uint16 |
copy | false | float32 | float64 | imag | int | int8 | int16 | uint32 |
int32 | int64 | iota | len | make | new | nil | panic | uint64 |
println | real | recover | string | true | uint | uint8 | uintptr |
二、Go程序的基本结构
package main import "fmt" func main() {
fmt.Println("hello world")
}
1. 任何一个代码文件隶属于一个包
2.import 关键字,引用其他包
import ("fmt")
import ("os")
通常习惯写成
import (
"fmt"
"os"
)
3.golang可执行程序,package main, 并且有且只有一个main入口函数
4.包中函数调用
a.同一个包中函数,直接调用
b.不同包中函数,通过包名+点+函数名进行调用
5.包访问控制权限
a.大写意味着这个函数/变量是可导出的
b.小写意味着这个函数/变量是私有的,包外部不能访问
小练习
1. 写一个程序,对给定一个数字n,求出所有两两相加等于n的组合
package main import "fmt" func list(n int) {
for i := 0; i <= n; i++ {
fmt.Printf("%d+%d=%d\n", i, n-i, n)
}
} func main() {
list(10)
} // go build -o bin/list.exe go_dev/day2/example1/main
练习1
2. 一个程序包含两个包add和main,其中add包中有两个变量:Name和age。请问main包中如何访问Name和age?
package add // 方式一
// var Name string = "hello world"
// var Age int = 10 // 方式一
// var Name string = "hello world"
// var Age int = 10 // 方式二
var Name string
var Age int func Test() {
Name = "hello wrold"
Age = 20
}
add.go
package main import (
"fmt"
"go_dev/day2/example2/add"
) func main() {
// 方式一 直接调用
// fmt.Println("Name=", add.Name)
// fmt.Println("Age=", add.Age) // 方式二 先调用函数
add.Test()
fmt.Println("Name=", add.Name)
fmt.Println("Age=", add.Age)
}
main.go
3. 包别名的应用,开发一个程序,使用包别名来访问包中的函数?
package main import (
"fmt"
a "go_dev/day2/example2/add"
) func main() {
// 方式一 直接调用
// fmt.Println("Name=", add.Name)
// fmt.Println("Age=", add.Age) // 方式二 先调用函数
// add.Test()
// fmt.Println("Name=", add.Name)
// fmt.Println("Age=", add.Age) // 包的别名
a.Test()
fmt.Println("Name=", a.Name)
fmt.Println("Age=", a.Age)
}
main.go
4. 每个源文件都可以包含一个init函数,这个init函数自动被go运行框架调用。开发一个程序演示这个功能?
package add // 先执行全局变量,在执行init函数, 在执行main函数 // 方式一
// var Name string = "hello world"
// var Age int = 10 // 方式二
var Name string
var Age int func Test() {
Name = "hello wrold"
Age = 20
} func init() {
Name = "hello wrold"
Age = 20
}
add.go
package main import (
"fmt"
// "go_dev/day2/example2/add"
a "go_dev/day2/example2/add"
) func main() {
// 方式一 直接调用
// fmt.Println("Name=", add.Name)
// fmt.Println("Age=", add.Age) // 方式二 先调用函数
// add.Test()
// fmt.Println("Name=", add.Name)
// fmt.Println("Age=", add.Age) // 包的别名
// a.Test()
// fmt.Println("Name=", a.Name)
// fmt.Println("Age=", a.Age) // init
fmt.Println("Name=", a.Name)
fmt.Println("Age=", a.Age)
}
main.go
5. 包的只初始化,不引用。请开发一个程序,演示这个做法
package test import "fmt" var Name string = "hello world"
var Age int = 1000 func init() {
fmt.Println("Name=", Name)
fmt.Println("Age=", Age) Age = 10
fmt.Println("Age=", Age)
fmt.Println("this is a test....")
}
test.go
package add import (
_ "go_dev/day2/example2/test"
)
add.go
三、函数声明和注释
1.函数声明:func 函数名字(参数列表)(返回值列表){}
2. 注释,两种注释,单行注释://和多行注释 /* */
四、常量和变量
1. 常量
- (1). changliang使用const修饰,代表永远是只读的,不能修改
- (2). const只能修饰boolean,number(int相关类型、浮点类型、complex)和string
- (3). 语法:const identifier[type] = value,其中type可以省略
- (4). 比较优雅的写法
const (
a = 0
b = 1
c = 2
)
- (5). 更加专业的写法
const (
a = iota
b // 1
c // 2
)
练习
1. 定义两个常量Man=1和Female=2,获取当前时间的秒数,如果能被Female整除,则在终端打印female,否则打印man。Second := time.Now().Unix()
package main import (
"fmt"
"time"
) const (
Man = 1
Female = 2
) func main() {
second := time.Now().Unix()
if second%Female == 0 {
fmt.Println("Female")
} else {
fmt.Println("Man")
}
}
main.go
2、变量
(1). 语法:var identifier type
例1
var a int
var b string
var c bool
var d int = 8
var e string = "hello world"
例2
var (
a int // 默认为0
b string // 默认为“”
c bool // 默认为false
d = 8
e = "hello world"
)
练习
1. 写一个程序获取当前运行的操作系统名称和PATH环境环境变量的值,并打印在终端。
package main import (
"fmt"
"os"
) func get_os() {
go_os := os.Getenv("GOOS")
fmt.Printf("the operaing system is: %s\n", go_os)
path := os.Getenv("PATH")
fmt.Printf("Path is: %s\n", path)
} func main() {
get_os()
}
main.go
变量的作用域
1. 在函数内部声明的变量叫做局部变量,生命周期仅限于函数内部。
2. 在函数外部声明的变量叫做全局变量,生命周期作用于整个包,如果是大写的,则作用于整个程序。
五、数据类型和操作符
1. 值类型和引用类型
值类型:变量直接存储值,内存通常在栈中分配
引用类型:变量存储的是一个地址,这个地址存储最终的值。内存通常在堆上分配。通过GC回收。
值类型:基本数据类型int、float、bool、string以及数组和struct
引用类型:指针、slice、map、chan等都是引用类型。
练习:
- 写一个程序用来打印值类型和引用类型变量到终端,并观察输出结果
package main import "fmt" func main() {
a := 5
b := make(chan int, 1) fmt.Println("a=", a)
fmt.Println("b=", b) } 输出
// a= 5
// b= 0xc00003a070
- 写一个程序,交换两个整数的值。比如: a=3; b=4; 交换之后:a=4;b=3
package main import "fmt" var n int = 100 /*
赋值语句只能在函数中, 以下情况都会报错
var a int
a = 100
或者
a := 100
*/ func swap(a int, b int) {
tmp := a
a = b
b = tmp
} func swap1(a int, b int) (int, int) {
return b, a
} func swap2(a *int, b *int) {
// 改变的是地址指向的那片内存的值
tmp := *a
*a = *b
*b = tmp
} func test() {
// 类型转换
var a int8 = 100
var b int16 = int16(a) // 赋值必须类型相同 fmt.Printf("a=%d, b=%d", a, b)
} func main() {
first := 10
second := 20 // 方式一
swap(first, second) // copy的是first和second的变量值 fmt.Println("first=", first)
fmt.Println("second=", second) // 方式二
a, b := swap1(first, second) fmt.Println("a=", a)
fmt.Println("b=", b) // 方式三
c, d := second, first fmt.Println("c=", c)
fmt.Println("d=", d) // 方式四
swap2(&first, &second) // copy的是first和second的地址 fmt.Println("first=", first)
fmt.Println("second=", second) test() }
交换a和b的四种方式
2. 数据类型和操作符
- 数据类型
(1) bool类型,只能存true或false
(2) 相关操作符,!、&&、||
(3) 数字类型,主要有int、int8、int16、int32、int64、uint8、uint16、uint32、uint64、float32、float64
(4) 类型转换,type(variable),比如:var a int=8; var b int32=int32(a)
(5) 字符类型:var a byte = 'c'
(6) 字符串类型:var str string = "hello world"
注:字符串表示两种方式:
1)“” 双引号:支持转义字符,如\n, \t, %%等等
2)`` (反引号): 不支持转义字符,内容按原样输出
- 操作符
(1) 逻辑操作符:=、!=、<、<=、>和>=
(2) 数学操作复:+、-、*、/ 等等
练习
- 使用math/rand生成10个随机整数,10个小于100的随机整数以及10个随机浮点数?
package main import (
"fmt"
"math/rand"
"time"
) func init() {
rand.Seed(time.Now().Unix())
} func main() { for i := 0; i < 10; i++ {
a := rand.Int()
fmt.Println(a)
} for i := 0; i < 10; i++ {
a := rand.Intn(100)
fmt.Println(a)
} for i := 0; i < 10; i++ {
a := rand.Float32()
fmt.Println(a)
}
}
main.go
- 字符串两种表示方式
package main import "fmt" func main() {
var str = "hello world\n"
var str1 = `
床前明月光,
疑是地上霜,
举头望明月,
低头思故乡。
`
var b byte = 'c' fmt.Println(str)
fmt.Println(str1)
fmt.Println(b)
fmt.Printf("%c\n", b)
} 输出:
hello world 床前明月光,
疑是地上霜,
举头望明月,
低头思故乡。 99
c
字符串两种表示方式
- 字符串逆转
package main import "fmt" func reverse(str string) string {
var result string
strlen := len(str)
for i := 0; i < strlen; i++ {
result = result + fmt.Sprintf("%c", str[strlen-i-1])
}
return result
} func reverse1(str string) string {
var result []byte
tmp := []byte(str)
length := len(str)
for i := 0; i < length; i++ {
result = append(result, tmp[length-i-1])
}
return string(result)
} func main() {
str1 := "hello"
str2 := "world" // str3 := str1 + " " + str2
str3 := fmt.Sprintf("%s %s", str1, str2)
n := len(str3) fmt.Println(str3)
fmt.Printf("len(str3)=%d\n", n) substr := str3[0:5]
fmt.Println(substr) substr = str3[6:]
fmt.Println(substr) result := reverse(str3)
fmt.Println(result) result1 := reverse1(str3)
fmt.Println(result1)
}
main.go
六、栈和堆
栈是在栈内存中分配的,公用的,性能最高, 堆是在系统内存中分配的
基本数据类型是在栈中存储的 引用数据类型是在堆中存储的
函数传参:做了一个拷贝,如果参数为变量值,则函数内部对变量做的操作不会影响实际变量的值。若传的参数为地址,则对地址指向变量的操作会影响实际变量的值。
package main import "fmt" func modify(a int) {
a = 10
return
} func modify1(a *int) {
*a = 10
} func main() {
a := 5
b := make(chan int, 1) fmt.Println("a=", a)
fmt.Println("b=", b) modify(a) // 做了一个拷贝, 不影响原来的值
fmt.Println("a=", a) modify1(&a) // 参数传了一个地址,对其指向的变量值进行操作会影响其地址指向的变量值
fmt.Println("a=", a)
} // 栈是在栈内存中分配的,公用的,性能最高, 堆是在系统内存中分配的
// 基本数据类型是在栈中存储的 引用数据类型是在堆中存储的 /*
a= 5
b= 0xc00008c000
a= 5
a= 10
*/
练习作业
- 1. 判断 101-200 之间有多少个素数,并输出所有素数。注:定义:为在大于1的自然数中,除了1和它本身以外不再有其他因数的数称为质数
- 2. 打印出100-999中所有的“水仙花数”,所谓“水仙花数”是指一个三位数,其各位数字立方和等于该数本身。例如:153 是一个“水仙花数”,因为 153=1 的三次方+5 的三次方+3 的三次方。
- 3. 对于一个数n,求n的阶乘之和,即: 1! + 2! + 3!+…n!
参考
// 判断 101-200 之间有多少个素数,并输出所有素数。
package main import (
"fmt"
"math"
) func isPrime(n int) bool {
sqrt_n := int(math.Sqrt(float64(n))) + 1
for i := 2; i < sqrt_n; i++ {
if n%i == 0 {
return false
}
}
return true
} func main() {
var n int
var m int fmt.Printf("请输入两个数字:")
fmt.Scanf("%d%d", &n, &m) for i := n; i < m; i++ {
if isPrime(i) == true {
fmt.Printf("%d\n", i)
}
}
}
作业一
/*
打印出100-999中所有的“水仙花数”,所谓“水仙花数”是指一个三位数,其各位数字立方和等于该数本身。
例如:153 是一个“水仙花数”,因为 153=1 的三次方+5 的三次方+3 的三次方。
*/ package main import (
"fmt"
"strconv"
) func isShuixianhua(n int) bool {
var i, j, k int
i = n % 10
j = (n / 10) % 10
k = (n / 100) % 10
sum := i*i*i + j*j*j + k*k*k
return sum == n
} func isShuixianhua2(n int) bool {
var result = 0
str := strconv.Itoa(n)
for i := 0; i < len(str); i++ {
num := int(str[i] - '')
result += (num * num * num)
}
number, err := strconv.Atoi(str)
if err != nil {
fmt.Printf("can not convert %s to int\n", str)
}
if result == number {
return true
}
return false
} func main() {
var n int
var m int fmt.Printf("请输入两个数字:")
fmt.Scanf("%d,%d", &n, &m) for i := n; i <= m; i++ {
if isShuixianhua(i) == true {
fmt.Println(i)
}
}
}
作业二
// 对于一个数n,求n的阶乘之和,即: 1! + 2! + 3!+…n! package main import "fmt" func sum(n int) uint64 {
var s uint64 = 1
var sum uint64 = 0
for i := 1; i <= n; i++ {
s = s * uint64(i)
fmt.Printf("%d!=%d\n", i, s)
sum += s
}
return sum
} func main() {
var n int fmt.Printf("请输入一个数字:")
fmt.Scanf("%d", &n) s := sum(n)
fmt.Println(s)
}
作业三
GO语言系列(二)- 基本数据类型和操作符的更多相关文章
- golang基础之二-基本数据类型和操作符
文件名&关键字&标识符 所有go源码都是以.go结尾 标识符以字母或下划线开头,大小写敏感 下划线_是特殊标识符,用户忽略结果 保留关键字 导入包时可以设置别名 下面是保留关键字: b ...
- Golang语言系列-02-常用数据类型
Go语言常用数据类型 Go 语言中有丰富的数据类型,除了基本的整型.浮点型.布尔型.字符串.byte/rune 之外, 还有数组.切片.函数.map.通道(channel).结构体等. Go语言的基本 ...
- Python语言系列-02-基础数据类型
格式化输出 #!/usr/bin/env python3 # author:Alnk(李成果) # 百分号% 格式化输出 name = input('姓名:') age = input('年龄:') ...
- 复习C语言系列二:动态调用函数指针数组
a:用call_fun_ptr调用afun(),b:用call_fun_ptr调用bfun() a 请输入给您指定的函数输调用的参数 afun_par ------------------------ ...
- Go语言系列(三)之数组和切片
<Go语言系列文章> Go语言系列(一)之Go的安装和使用 Go语言系列(二)之基础语法总结 1. 数组 数组用于存储若干个相同类型的变量的集合.数组中每个变量称为数组的元素,每个元素都有 ...
- OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章)
OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章) 4.5精度和精度修饰符 4.5.1范围和精度 用于存储和展示浮点数.整数变量的范围和精度依赖于数值的源(varying,unifo ...
- Redis系列(二):Redis的数据类型及命令操作
原文链接(转载请注明出处):Redis系列(二):Redis的数据类型及命令操作 Redis 中常用命令 Redis 官方的文档是英文版的,当然网上也有大量的中文翻译版,例如:Redis 命令参考.这 ...
- go 从入门到精通(二)基本数据类型和操作符
一.文件名&关键字&标识符 所有go源码都是以.go结尾 标识符以字母或下划线开头,大小写敏感 下划线_是特殊标识符,用户忽略结果 保留关键字 导入包时可以设置别名 下面是保留关键字: ...
- C语言高速入门系列(二)
C语言高速入门系列(二) -----转载请注明出处coder-pig 本节引言: 在前面一节中我们对C语言进行了初步的了解,学会了使用IDE进行代码的编写,编译执行! 在这一节中我们会对C语言的基本的 ...
随机推荐
- 前后端分离djangorestframework——认证组件
authentication 认证是干嘛的已经不需要多说.而前后端未分离的认证基本是用cookie或者session,前后端分离的一般用token 全局认证 先创建一个django项目,项目名为drf ...
- c/c++ 拷贝控制 右值与const引用
拷贝控制 右值与const引用 背景:当一个函数的返回值是自定义类型时,调用侧用什么类型接收?? 1,如果自定义类型的拷贝构造函数的参数用const修饰了:可以用下面的方式接收. Test t2 = ...
- c/c++ 网络编程 UDP 用if_nameindex和ioctl取得主机网络信息
网络编程 UDP 用if_nameindex和ioctl取得主机网络信息 getifaddrs函数取得的东西太多了,如果只想取得网卡名字和网卡编号可以用下面的2个函数. 1,if_nameindex ...
- LeetCode算法题-Diameter of Binary Tree(Java实现)
这是悦乐书的第257次更新,第270篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第124题(顺位题号是543).给定二叉树,您需要计算树的直径长度. 二叉树的直径是树中 ...
- JavaScript对象类型之创建对象
引言 JavaScript中,可以通过对象直接量,关键字new(ECMAScript 5中的)Object.create(),函数来创建对象. 对象直接量 JavaScript中使用对象直接量来创建对 ...
- linux环境下快速安装Mariadb和Redis
一 Mariadb(Mysql)篇 1.新建一个yum源仓库 touch /etc/yum.repos.d/Mariadb.repo 2.在这个yum源仓库文件中,添加仓库url地址 [mariadb ...
- pip install urllib3[secure] 报错 error: ffi.h: No such file or directory
解决 sudo apt-get install build-essential autoconf libtool pkg-config python-opengl python-imaging pyt ...
- 错误代码1045 Access denied for user 'root'@'localhost' (using password:YES)
在mysql中新建连接,ip地址是127.0.0.1,账号是root,密码是123456,但是测试连接的时候报错, 错误代码1045 Access denied for user 'root'@'lo ...
- THUWC2019:Reach out
竟然还有机会去THUWC!!! 不过没有上WC线感觉有点可惜-- Day -INF~Day -2 考完NOIP两周滚回来被神仙们吊打 先是做专题,为什么会选到构造啊(ノ`Д)ノ 我构造专题有7道题留作 ...
- Golang 入门 : 切片(slice)
切片(slice)是 Golang 中一种比较特殊的数据结构,这种数据结构更便于使用和管理数据集合.切片是围绕动态数组的概念构建的,可以按需自动增长和缩小.切片的动态增长是通过内置函数 append( ...