输入与输出
变量
运算符
常量与常量生成器
基本数据类型
整型
浮点型
布尔型
字符型
字符串型
字符串的常用操作
输入输出
回到顶部↑↑↑输入与输出都需要导入fmt
包,输入使用的是fmt.Scanf("verb", &变量名)
,其中,&
是取地址符,比如下面示例代码中,将输入的值分别用name
与age
接收,就需要使用&
。输出使用的是fmt.Println()
,其中,Println()
表示按行输出,也就是每输出一次,就会换一行,相当于自动加上了\n
,另外还有Printf()
、Print()
;
package main
import "fmt"
func main() {
var name, age string
// 提示信息
fmt.Println("请输入姓名和年龄: ")
// 接收用户输入
// Scanln()
// fmt.Scanln(&name, &age)
// 输入: xiaoming 17
// 显示结果:您输入的是: xiaoming 17
// Scanf()
fmt.Scanf("%s\n%s", &name, &age) // 老王 23
fmt.Println("您输入的是: ", name, age) // 老王 23
}
package main
import "fmt"
func main() {
// Println()打印一条语句后会自动换行
fmt.Println("hello world")
fmt.Println("hello world 2")
// Print()打印一条语句后不会自动换行
fmt.Print("a", "b")
fmt.Print("c", "d")
// Sprint()的结果不直接打印,需要变量接收
fmt.Sprint("1", "2")
s := fmt.Sprint("3", "4")
fmt.Println(s)
// fmt.Fprint()
fmt.Printf("%d \n", 19) // 19
fmt.Printf("%x %X \n", 12, 13) // c D
// 获取内存地址
v := 5
fmt.Printf("%p \n", &v) // 0xc00000a100
// 表示百分号 %%
fmt.Printf("\n 增长率为%d%%", 20)
}
变量
回到顶部↑↑↑package main
import "fmt"
func main() {
// 定义变量
var name string
// 变量赋值
name = "小明"
fmt.Println("名字是:", name) // 名字是: 小明
// 也可以声明同时赋值
var age int = 20
fmt.Println("年龄是:", age) // 年龄是: 20
// 声明同时赋值(省略类型)
var gender = "男"
fmt.Println("性别是:", gender) // 性别是: 男
// 短变量(只能在函数中使用,不能作为全局变量, 平时使用较多的一种方式)
//语法: 变量 := 值
score := 97
fmt.Println("得分是: ", score) // 得分是: 97
// 同时声明多个变量,先声明后赋值, 类型要相同
var a, b, c int
a, b, c = 1, 2, 3
fmt.Println(a, b, c) // 1 2 3
// 同时声明多个变量并赋值,类型可以省略,可以同时赋值不同类型
var d, e, f = 5, 9.2, true
fmt.Println(d, e, f) // 5 9.2 true
// 同时声明多个变量并赋值,另一种方式
var (
x = "你好"
y = false
z = 666
)
fmt.Println(x, y, z) // 你好 false 666
// 使用短变量声明并赋值多个变量时,要求必须至少有一个变量没有被声明过
var (
m = 1
n = 2
)
// m, n := 3, 4 // .\variable.go:52:7: no new variables on left side of :=
n, l := 3, 4
fmt.Println(m, n, l) // 1 3 4
}
常量与常量生成器
package main
import "fmt"
// 常量
// 常量是一个固定值,在编译期就确定了结果,声明常量时必须赋值,且结果不可以改变
// 定义常量的关键字 const
// 常量与变量的区别是,常量定义了之后可以不使用,但是变量定义后必须使用,否则编译报错
// 常量的定义没有明确的语法要求,可以使用驼峰命名法;
// 经常定义为常量的例子: 名字, 电话号码, 圆周率......
// 常量的值可以是表达式,但是不允许出现变量;
// 定义常量时,如果不是必须制定特定类型,可以省略类型,使用默认类型, 而且数值类型的常量可以直接进行运算;
func main() {
const Name string = "xiaoming"
const Age = 23 // 默认int
const Result = 3 * 4 + 2 // 不要指定类型
const Num = 1.77 // 默认float64
fmt.Println(Name)
fmt.Println(Age)
fmt.Printf("%T \n%T \n%T \n", Age, Result, Num) // int int float64
fmt.Println(Age + Result) // 37
// 官方推荐常量定义方式: const(常量1=值1 \n 常量2=值2 \n 常量3=值3), 如:
const (
Gender = "男"
Class = 1
Grade = "八"
)
fmt.Println(Gender, Class, Grade) // 男 1 八
// 在定义多个变量时,第一个常量必须赋值,如果后一个变量没有赋值,就默认与前一个相等,如
const (
A = 1
B
C
D = 2
E
)
fmt.Println(A, B, C, D, E) // 1 1 1 2 2
// 常量生成器 iota
// 当一组常量都是数值类型,可以使用常量生成器iota指定这组常量按照特定的规则变化
// iota起始值为0, 每次增加1, 如:
const (
X = iota
Y
Z
// 上面相当于 X = iota Y = iota Z = iota
)
fmt.Println(X, Y, Z) // 0 1 2
const (
L = iota + 10 // 从10开始
M
N
)
fmt.Println(L, M, N) // 10 11 12
const (
P = iota << 1 // 左移一位,即乘以2
Q
R
)
fmt.Println(P, Q, R) // 0 2 4
const (
U = 10 // iota=0 // 明确赋值10 即10;
V = iota // iota=1 // 没有明确赋值,此时iota已经为1;
W // iota=2 // 没有明确赋值,与上一个值一样为iota,但是此时iota已经为2;
)
fmt.Println(U, V, W) // 10 1 2
// 再来个例子,加深对iota的理解, iota 不管有没有用,都在从0自增,如果有值会覆盖没值就会用iota的值
const (
a = iota // iota=0
b // iota=1
c = 9 // iota=2 9
d // iota=3 9 与上一个一样
e = iota // iota=4
f // iota=5
g // iota=6
)
fmt.Println(a, b, c, d, e, f, g) // 0 1 9 9 4 5 6
}
运算符
回到顶部↑↑↑package main
import "fmt"
// 运算符:算术运算符、比较运算符、逻辑运算符、赋值运算符、关系运算符、位运算符等
func main() {
// 算术运算符 + - * / % ++ --, 依次为:加、减、乘、除、取余、自增1、自减1
// 自增、自减示例,注:自增和自减都只能单独使用,没有返回值;
a, b := 2, 5
a++ // 即 a = a + 1
b-- // 即 b = b - 1
fmt.Println(a, b) // 3 4
// 比较运算符
// == != > >= < <=
// 逻辑运算符
// ! && ||
// 运算符优先级
// 乘除 > 取余 > 加减
// 比较运算符 > 逻辑运算符
// 赋值运算符
// = += -= *= /=
// 位运算符
// 正数在计算机中二进制还是原值, 负数在计算机中存储的是补码
/*
原码:正数的原码还是正数;负数的原码是负数绝对值的二进制表示;以8位二进制表示;
反码:正数的反码还是正数;负数的反码是所有位取反;
补码:正数的补码还是正数;负数的补码为负数的反码加一;负数的补码就是负数在计算机中的二进制表示;
想要知道负数二进制对应的十进制数字就是补码 --> 反码 --> 原码 --> 添加负号
如果是16位只需要在负数前面添加8个1,正数前面添加8个0
*/
// 示例:
// 原码
// 原码为:0000 0011
var c int8 = 3
// 原码为:0000 0001
var d int8 = -2
fmt.Println(c, d)
// 反码
// 反码为:0000 0011
var e int8 = 3
// 反码为:1111 1101
var f int8 = -2
fmt.Println(e, f)
// 补码
// 补码为:0000 0011
var g int8 = 3
// 补码为:1111 1110
var h int8 = -2
fmt.Println(g, h)
// 如何区分正负数?
// 首位为0是正数;首位为1是负数;
// go语言中的位运算符,算法中使用频率较高,区块链、密码学使用较多;
// << 二进制左移
// >> 二进制右移
// | 位运算或OR,有1取"1"
// & 位运算AND,转换二进制,都为1取1
// ^ 位运算异或XOR,二阶运算相同为0不同为1,;一阶运算加一后正数交互(正数变负数,负数变正数)
// &^ 位清空(AND NOT),如果右侧0左侧不变,如果右侧为1,左侧一定清零,a&^b = a&(^b)
var i int8 = 3
// 原码:0000 0011
// 反码:0000 0011
// 补码:0000 0011
var j int8 = -2
// 原码:0000 0010
// 反码:1111 1101
// 补码:1111 1110
// 正数:左移几位就是乘以2的几次方;右移几位就是除以2的几次方,最小值为0;
fmt.Println(i << 2) // 0000 1100 = 8 + 4 = 12
fmt.Println(i >> 2) // 0000 0000 = 0
// 负数:左移几位就是乘以2的几次方;右移几位就是除以2的几次方,最小值为-1;注意:操作的是原码,再加负号;
fmt.Println(j << 2) // 0000 1000 --> 负数,-8
fmt.Println(j >> 2) // 0000 0001 --> 负数,-1
fmt.Println(j >> 1) // 0000 0001 --> 负数,-1
fmt.Println("下面是位运算或:")
fmt.Println(i | j) // 有负数,用两数的补码,有1取1,得到补码1111 1111 --> 反码 1111 1110 --> 原码 0000 0001, 补码首位为1,负数,所以为-1;
fmt.Println("下面是位运算与:")
fmt.Println(i & j) // 有负数,用两数的补码,都为1取1,得到补码0000 0010 --> 反码 0000 0010 --> 原码 0000 0010, 补码首位为0,正数,2;
fmt.Println("下面是位运算异或:")
fmt.Println(i ^ j) // 有负数,用两数的补码,同0异1,得到补码1111 1101 --> 反码 1111 1100 --> 原码 0000 0011, 补码首位为1,负数,-3;
fmt.Println("下面是位清空:")
fmt.Println(i &^ j) // 有负数,用两数的补码,同0异1,得到补码0000 0001--> 反码 0000 0001 --> 原码 0000 0001, 补码首位为0,正数,1;
}
基本数据类型
整型
回到顶部↑↑↑package main
import "fmt"
// 整型
func main() {
var a int8 = 8
var b int16 = 16
var c int32 = 32
var d int64 = 64
var e int = 65 // 这个int可以省略,go语言中默认是int类型
fmt.Println(a, b, c, d, e) // 8 16 32 64 65
// 类型不同,不能相加
// fmt.Println(a+b) // invalid operation: a + b (mismatched types int8 and int16)
//类型转换,语法:类型(值)
// 比如将b转化为int8类型,就可以与a相加了
fmt.Println(a + int8(b)) // 24
// 定义不同进制的数,打印时候都是以十进制显示
// 十进制
d = 19
fmt.Println(d) // 19
// 八进制
o := 023
fmt.Println(o) // 19
// 十六进制
x := 0x13
fmt.Println(x) // 19
// 将结果以二进制显示
s := fmt.Sprintf("%b", d)
fmt.Println(s) // 10011
// ex表示10的x次方
m := 2e5
fmt.Println(m) // 200000
}
浮点型
回到顶部↑↑↑package main
import (
"fmt"
"math"
)
// 浮点数
func main() {
var f float64 = 1
var i int = 2
// f = i // cannot use i (type int) as type float64 in assignment
f = float64(i)
fmt.Println(f, i) // 2 2
// 使用math包查看float32和float64等的最大值
fmt.Println(math.MaxFloat32) // 3.4028234663852886e+38
fmt.Println(math.MaxFloat64) // 1.7976931348623157e+308
fmt.Println(math.MaxInt8) // 127
fmt.Println(math.MaxInt16) // 32767
fmt.Println(math.MaxInt32) // 2147483647
fmt.Println(math.MaxInt64) // 9223372036854775807
//浮点类型之间相互转化
var a float32 = 1.4
var b float64 = 1.6
// fmt.Println(a + b) // invalid operation: a + b (mismatched types float32 and float64)
fmt.Println(float64(a) + b) // 2.999999976158142
fmt.Println(a + float32(b)) // 3
// 验证运算前后数据类型一致
var a1, a2 int = 3, 2
var b1, b2 float64 = 3, 2
fmt.Println(a1 / a2) // 1
fmt.Println(b1 / b2) // 1.5
}
布尔型
回到顶部↑↑↑package main
import (
"fmt"
"unsafe"
)
// 布尔类型
// 布尔类型只占用一个字节
func main() {
var a bool = true
var b bool = false
var c = true
d := false
fmt.Println(a, b, c, d) // true false true false
// 查看占用内存大小 unsafe.Sizeof()
fmt.Println(unsafe.Sizeof(a)) // 1
var e byte = 1 // 1个字节
var f int8 = 2 // 1个字节
var g int = 1 // 8个字节
fmt.Println(unsafe.Sizeof(e), unsafe.Sizeof(f), unsafe.Sizeof(g)) // 1 1 8
// 通过表达式来给变量赋值布尔类型
h := 4 > 1
fmt.Println(h) // true
}
字符型
回到顶部↑↑↑package main
import "fmt"
func main() {
i := 65
j := 97
k := 24352
l := 0x738B
fmt.Println(i, j, k) // 65 97 24352
fmt.Printf("%c\n", i) // A
fmt.Printf("%c\n", j) // a
fmt.Printf("%c\n", k) // 张
fmt.Printf("%c\n", l) // 王
}
字符串型
回到顶部↑↑↑package main
import (
"fmt"
"strconv"
)
// 字符串类型
func main() {
/*
string
字符串是一段不可变的字符序列,内容可以任意,可以是一段字符,也可以是一串数字,
但是数字字符串不能直接进行数学运算,必须转化成整型或者浮点型才能进行数学运算;
字符串两侧使用英文的双引号,内容支持转义字符转义,两侧使用反单引号时原格式输出;
字符串的加法是字符串拼接,如"1" + "2" = "12"
*/
// 创建字符串变量的方式:
var s string = "hello"
name := "Tom"
fmt.Println(s) // hello
fmt.Println(name) // Tom
var s2 string = `world`
var s3 string = `"world"`
fmt.Println(s2) // world
fmt.Println(s3) // "world"
// 再如:
a := "a\tb"
b := `a\tb`
fmt.Println(a) // a b
fmt.Println(b) // a\tb
// 字符串和数值转换,strconv包提供了字符串和其他类型转化的函数
// int 和string互相转化,strconv.ParseInt()
s4 := "11"
i, j := strconv.ParseInt(s4, 10, 64) // 返回值有2个,必须要两个变量接收,或者第二个变量使用_占位
fmt.Println(i) // 11
fmt.Println(j) // <nil> 表示正常运行,没有出错
i2, _ := strconv.ParseInt(s4, 8, 64)
i3, _ := strconv.ParseInt(s4, 16, 64)
fmt.Println(i2) // 9
fmt.Println(i3) // 17
// 默认转十进制,strconv.Atoi()
t, _ := strconv.Atoi(s4)
fmt.Println(t) // 11
// 整型转字符串, strconv.FormatInt()
var m int = 11
// i4 := strconv.FormatInt(m, 10) // 要求传的参数是int64,所以需要转化
i4 := strconv.FormatInt(int64(m), 10)
fmt.Println(i4) // "11"
// 或者使用strconv.Itoa(),默认十进制
i5 := strconv.Itoa(11)
fmt.Println(i5) // "11"
}
字符串常用操作
回到顶部↑↑↑package main
// 字符串的常用方法,切片
import (
"fmt"
"strings"
)
func main() {
// 1.len(字符串)获取字符串的字节长度,注意,是字节长度,一个字母占用1个字节长度,一个汉字占用3个字节长度
var s1 string = "abcde"
fmt.Println(len(s1)) // 5
var s2 string = "你好"
fmt.Println(len(s2)) // 6
// 2. 可以使用 变量名[n] 获取到字符串第 n+1 个字节
var s3 = "abcd"
fmt.Println(s3[2])
s4 := s3[0]
fmt.Println(s4) // 97
fmt.Printf("%T\n", s4) // uint8
s5 := fmt.Sprint(s4)
fmt.Println(s5) // 97
fmt.Printf("%T\n", s5) // string
// 注意,汉字的索引需要3个,拆开会乱码
s6 := "go语言入门教程1"
fmt.Printf("s6的字节长度是: %d \n", len(s6)) // s6的字节长度是: 21
fmt.Printf("s6的索引0是: %s \n", s6[0]) // s6的索引0是: %!s(uint8=103)
fmt.Printf("s6的索引0是: %c \n", s6[0]) // s6的索引0是: g
fmt.Printf("s6的索引1是: %s \n", s6[1]) // s6的索引1是: %!s(uint8=111)
fmt.Printf("s6的索引1是: %c \n", s6[1]) // s6的索引1是: o
fmt.Printf("s6的索引2是: %s \n", s6[2]) // s6的索引2是: %!s(uint8=232)
fmt.Printf("s6的索引2是: %c \n", s6[2]) // s6的索引2是: è
fmt.Printf("s6的索引3是: %s \n", s6[2]) // s6的索引2是: %!s(uint8=232)
fmt.Printf("s6的索引3是: %c \n", s6[2]) // s6的索引2是: è
fmt.Printf("s6的索引20是: %s \n", s6[20]) // s6的索引20是: %!s(uint8=49)
fmt.Printf("s6的索引20是: %c \n", s6[20]) // s6的索引20是: 1
// 切片,注意,字符串[m:n],表示的是大于等于m,小于n,即m, m+1, m+2......n-1,也就是左闭右开区间;
fmt.Printf("s6的索引2~5是: %c \n", s6[2:5]) // s6的索引2~5是: %!c(string=语)
fmt.Printf("s6的索引5~8是: %c \n", s6[5:8]) // s6的索引5~8是: %!c(string=言)
fmt.Printf("s6的索引2~5是: %s \n", s6[2:5]) // s6的索引2~5是: 语
fmt.Printf("s6的索引5~8是: %s \n", s6[5:8]) // s6的索引5~8是: 言
fmt.Printf("s6的索引2到结尾是: %s \n", s6[2:]) // s6的索引2到结尾是: 语言入门教程1
// 3.字符长度,计算字符长度时,一个汉字是一个字符长度;注意与“字节长度”区分
// 如果想获取字符的个数,而不是字节数,那么需要将字符转换为rune类型的切片才行
// byte 等同于int8,常用来处理ascii字符
// rune 等同于int32,常用来处理unicode或utf-8字符
s7 := "go语言实战项目"
s8 := []rune(s7)
fmt.Printf("s7的字符长度是:%d\n", len(s8)) // 8
// for循环切片
fmt.Println("for循环start")
for _, n := range s7 {
fmt.Printf("%c \n", n)
}
fmt.Println("for循环end")
/*
for循环start
g
o
语
言
实
战
项
目
for循环end
*/
// 字符串其他方法
s9 := "go语言进阶go"
// 指定字符对应的索引
fmt.Printf("第一个g出现的位置是: %d \n", strings.Index(s9, "g")) // 第一个g出现的位置是: 0
fmt.Printf("第一个o出现的位置是: %d \n", strings.Index(s9, "o")) // 第一个o出现的位置是: 1
fmt.Printf("最后一个g出现的位置是: %d \n", strings.LastIndex(s9, "g")) // 最后一个g出现的位置是: 14
fmt.Printf("最后一个o出现的位置是: %d \n", strings.LastIndex(s9, "o")) // 最后一个o出现的位置是: 15
// 判断是否以XXX开头或结尾
// 判断开头 strings.HasPrefix(字符串变量, 目标)
fmt.Println(strings.HasPrefix(s9, "g")) // true
fmt.Println(strings.HasPrefix(s9, "go")) // true
fmt.Println(strings.HasPrefix(s9, "语言")) // false
// 判断结尾 strings.HasSuffix(字符串变量, 目标)
fmt.Println(strings.HasSuffix(s9, "g")) // false
fmt.Println(strings.HasSuffix(s9, "go")) // true
fmt.Println(strings.HasSuffix(s9, "阶")) // false
// 判断是否包含XXX, strings.Contains(字符串变量, 目标)
fmt.Println(strings.Contains(s9, "g")) // true
fmt.Println(strings.Contains(s9, "go")) // true
fmt.Println(strings.Contains(s9, "语言")) // true
fmt.Println(strings.Contains(s9, "开发")) // false
// 转换大小写(英文字母)
s10 := "Hello world"
// 全都变小写
fmt.Println(strings.ToLower(s10)) // hello world
//全都变大写
fmt.Println(strings.ToUpper(s10)) // HELLO WORLD
// 变标题?常理来说,应该是只有首字母大写,点进去看源码介绍
fmt.Println(strings.ToTitle(s10)) // HELLO WORLD
// ToUpper returns s with all Unicode letters mapped to their upper case.
// ToTitle returns a copy of the string s with all Unicode letters mapped to their Unicode title case.
// 字符串替换
// 替换指定次数:strings.Replace(字符串变量, 旧字符串, 新字符串, 替换次数)
// 替换所有:strings.ReplaceAll(字符串变量, 旧字符串, 新字符串)
s11 := "abcabcabc"
fmt.Println(strings.Replace(s11, "a", "A", 1)) // Abcabcabc
fmt.Println(strings.Replace(s11, "a", "A", 2)) // AbcAbcabc
fmt.Println(strings.ReplaceAll(s11, "a", "A")) // AbcAbcAbc
// 字符串重复 strings.Repeat(字符串变量, 重复次数)
s12 := "abcde"
s13 := "abc"
fmt.Println(strings.Repeat(s12, 2)) // abcdeabcde
fmt.Println(strings.Repeat(s13, 3)) // abcabcabc
// 字符串去掉指定字符 strings.Trim(字符串变量, 要去掉的字符), 去掉空格 strings.TrimSpace(字符串变量)
s14 := "abcdeabcde"
s15 := "abcdaaa"
s16 := " ab cdea bcde "
fmt.Println(strings.Trim(s14, "a")) // bcdeabcde
fmt.Println(strings.Trim(s15, "a")) // bcd
fmt.Println(strings.Trim(s15, "ac")) // bcd
fmt.Println(strings.Trim(s15, "ab")) // cd
fmt.Println(strings.Trim(s16, " ")) // ab cdea bcde
fmt.Println(strings.TrimSpace(s16)) // ab cdea bcde
// 字符串拼接 strings.Join(切片内容, 拼接符号)
arr := []string{"he", "ll", "ow", "or", "ld"}
fmt.Println(strings.Join(arr, "")) // helloworld
fmt.Println(strings.Join(arr, "-")) // he-ll-ow-or-ld
}