parent
426ab21720
commit
b9bcbcdb7d
|
@ -0,0 +1,92 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
|
||||
//type IP byte
|
||||
|
||||
// 常量表达式的值在编译期计算,而不是在运行期。
|
||||
// 每种常量的潜在类型都是基础类型:boolean、string或数字。
|
||||
func main() {
|
||||
const (
|
||||
PI = 3.14
|
||||
e = 2.72
|
||||
)
|
||||
fmt.Println(math.Pi)
|
||||
fmt.Println(math.E)
|
||||
fmt.Println(PI)
|
||||
fmt.Println(e)
|
||||
|
||||
// 所有常量的运算都可以在编译期完成,这样可以减少运行时的工作,
|
||||
// 也方便其他编译优化。当操作数是常量时,
|
||||
// 一些运行时的错误也可以在编译时被发现,
|
||||
// 例如整数除零、字符串索引越界、任何导致无效浮点数的操作等。
|
||||
|
||||
// 常量间的所有算术运算、逻辑运算和比较运算的结果也是常量,
|
||||
// 对常量的类型转换操作或以下函数调用都是返回常量结果:
|
||||
// len、cap、real、imag、complex和unsafe.Sizeof(§13.1)。
|
||||
|
||||
// 因为它们的值是在编译期就确定的,因此常量可以是构成类型的一部分,
|
||||
// 例如用于指定数组类型的长度:
|
||||
//const IPv4Len = 4
|
||||
// parseIPv4 parses an IPv4 address (d.d.d.d).
|
||||
//parseIPv4 := func(s string) IP {
|
||||
// var p [IPv4Len]byte
|
||||
// // ...
|
||||
// return p
|
||||
//}
|
||||
// 一个常量的声明也可以包含一个类型和一个值,但是如果没有显式指明类型,
|
||||
// 那么将从右边的表达式推断类型。在下面的代码中,
|
||||
// time.Duration是一个命名类型,底层类型是int64,time.Minute是对应类型的常量。
|
||||
// 下面声明的两个常量都是time.Duration类型,可以通过%T参数打印类型信息:
|
||||
const noDelay time.Duration = 0
|
||||
const timeout = 5 * time.Minute
|
||||
fmt.Printf("%T %[1]v\n", noDelay) // "time.Duration 0"
|
||||
fmt.Printf("%T %[1]v\n", timeout) // "time.Duration 5m0s"
|
||||
fmt.Printf("%T %[1]v\n", time.Minute) // "time.Duration 1m0s"
|
||||
|
||||
// 如果是批量声明的常量,除了第一个外其它的常量右边的初始化表达式都可以省略,
|
||||
// 如果省略初始化表达式则表示使用前面常量的初始化表达式写法,对应的常量类型也一样的。例如:
|
||||
const (
|
||||
a = 1
|
||||
b
|
||||
c = 2
|
||||
d
|
||||
)
|
||||
|
||||
fmt.Println(a, b, c, d) // "1 1 2 2"
|
||||
|
||||
// 下面是来自time包的例子,它首先定义了一个Weekday命名类型,
|
||||
// 然后为一周的每天定义了一个常量,从周日0开始。在其它编程语言中,
|
||||
// 这种类型一般被称为枚举类型。
|
||||
|
||||
type Weekday int
|
||||
|
||||
const (
|
||||
Sunday Weekday = iota
|
||||
Monday
|
||||
Tuesday
|
||||
Wednesday
|
||||
Thursday
|
||||
Friday
|
||||
Saturday
|
||||
)
|
||||
fmt.Printf("%T %[1]v \n", Sunday)
|
||||
|
||||
// 下面是一个更复杂的例子,每个常量都是1024的幂:
|
||||
const (
|
||||
_ = 1 << (10 * iota)
|
||||
KiB // 1024
|
||||
MiB // 1048576
|
||||
GiB // 1073741824
|
||||
TiB // 1099511627776 (exceeds 1 << 32)
|
||||
PiB // 1125899906842624
|
||||
EiB // 1152921504606846976
|
||||
ZiB // 1180591620717411303424 (exceeds 1 << 64)
|
||||
YiB // 1208925819614629174706176
|
||||
)
|
||||
fmt.Println(KiB)
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// 一个字符串是一个不可改变的字节序列。
|
||||
// 字符串可以包含任意的数据,包括byte值0,但是通常是用来包含人类可读的文本。
|
||||
// 文本字符串通常被解释为采用UTF8编码的Unicode码点(rune)序列,我们稍后会详细讨论这个问题。
|
||||
|
||||
func main() {
|
||||
// 字符串是一个不可以改变的数据序列
|
||||
// 相当于常量
|
||||
fmt.Println("I study golang")
|
||||
|
||||
// 内置的len函数可以返回一个字符串中的字节数目(不是rune字符数目),
|
||||
// 索引操作s[i]返回第i个字节的字节值,i必须满足0 ≤ i< len(s)条件约束。
|
||||
|
||||
// 字符串类型变量是一个字符集合。
|
||||
var str1 string = "Hello, world"
|
||||
fmt.Println(len(str1))
|
||||
fmt.Println(str1[0], str1[7])
|
||||
// 不可以越界访问字符
|
||||
//fmt.Println(str1[len(str1)]) //panic:index out of range
|
||||
|
||||
// 第i个字节并不一定是字符串的第i个字符,
|
||||
// 因为对于非ASCII字符的UTF8编码会要两个或多个字节。
|
||||
// 字符串可以拼接成一个新的字符串
|
||||
str2 := str1 + "。Goodbye"
|
||||
fmt.Println(str2)
|
||||
|
||||
// 字符串可以用==和<进行比较;比较通过逐个字节比较完成的,因此比较的结果是字符串自然编码的顺序。
|
||||
fmt.Println("ABC" == "ABC") // true
|
||||
|
||||
// 字符串的值是不可以呗改变的,当然其内部字符也是不可以改变的
|
||||
//str1[0] = 'a' //cannot assign to str1[0] (value of type byte)
|
||||
|
||||
// 但是可以将字符串变量赋予一个新的字符串来修改字符串变量的值
|
||||
fmt.Println(str1) // Hello, world
|
||||
str1 = "ABC"
|
||||
fmt.Println(str1) // ABC
|
||||
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 数组是一个由固定长度的特定类型元素组成的序列,
|
||||
// 一个数组可以由零个或多个元素组成。
|
||||
// 因为数组的长度是固定的,因此在Go语言中很少直接使用数组。
|
||||
// 和数组对应的类型是Slice(切片),它是可以增长和收缩的动态序列,
|
||||
// slice功能也更灵活,但是要理解slice工作原理的话需要先理解数组。
|
||||
|
||||
// 数组的每个元素可以通过索引下标来访问,
|
||||
// 索引下标的范围是从0开始到数组长度减1的位置。
|
||||
// 内置的len函数将返回数组中元素的个数。
|
||||
var arr1 [5]int = [5]int{4, 5, 6, 7, 8}
|
||||
fmt.Printf("%T %[1]v %d\n", arr1, len(arr1))
|
||||
|
||||
// 可以使用range 配合 for循环来遍历数组
|
||||
arr2 := [6]int{4, 5, 6, 7, 8, 9}
|
||||
for i, j := range arr2 {
|
||||
fmt.Printf("[%d] %d\n", i, j)
|
||||
}
|
||||
|
||||
// 我们将会发现,数组、slice、map和结构体字面值的写法都很相似.
|
||||
// 上面的形式是直接提供顺序初始化值序列,
|
||||
// 但是也可以指定一个索引和对应值列表的方式初始化,就像下面这样
|
||||
type Currency int
|
||||
|
||||
const (
|
||||
USD Currency = iota // 美元
|
||||
EUR // 欧元
|
||||
GBP // 英镑
|
||||
RMB // 人民币
|
||||
)
|
||||
symbol := [...]string{USD: "$", EUR: "€", GBP: "£", RMB: "¥"}
|
||||
fmt.Println(RMB, symbol[RMB]) // "3 ¥"
|
||||
|
||||
// 定义了一个含有100个元素的数组str3,最后2个元素被初始化为3和-1,其它元素都是用0初始化。
|
||||
str3 := [...]int{98: 3, -1}
|
||||
fmt.Printf("%T %[1]v \n", str3)
|
||||
|
||||
slice := []int{1, 2, 3}
|
||||
fmt.Printf("%T \n", slice)
|
||||
|
||||
// practice4.1
|
||||
diffSHA256 := func(str string) int {
|
||||
sha1 := sha256.Sum256([]byte(strings.ToLower(str)))
|
||||
sha2 := sha256.Sum256([]byte(strings.ToUpper(str)))
|
||||
fmt.Printf("%x \n%x \n", sha1, sha2)
|
||||
diff := 0
|
||||
for i, _ := range sha1 {
|
||||
if sha1[i] != sha2[i] {
|
||||
diff++
|
||||
}
|
||||
}
|
||||
return diff
|
||||
}
|
||||
fmt.Printf("%d", diffSHA256("xxx"))
|
||||
|
||||
}
|
Loading…
Reference in New Issue