#6 Golang: 格式化输出
Golang 2020-12-06Golang 格式化输出靠 fmt
库。
(f|s)?(scan|print)(f|ln)?
一组合就有 18 个方法了,再加上一个 Errorf
。
coding in a complicated world
Golang 格式化输出靠 fmt
库。
(f|s)?(scan|print)(f|ln)?
一组合就有 18 个方法了,再加上一个 Errorf
。
new
和 make
$ go doc builtin.new
package builtin // import "builtin"
func new(Type) *Type
The new built-in function allocates memory. The first argument is a type,
not a value, and the value returned is a pointer to a newly allocated zero
value of that type.
$ go doc builtin.make
package builtin // import "builtin"
func make(t Type, size ...IntegerType) Type
The make built-in function allocates and initializes an object of type
slice, map, or chan (only). Like new, the first argument is a type, not a
value. Unlike new, make's return type is the same as the type of its
argument, not a pointer to it. The specification of the result depends on
the type:
Slice: The size specifies the length. The capacity of the slice is
equal to its length. A second integer argument may be provided to
specify a different capacity; it must be no smaller than the
length. For example, make([]int, 0, 10) allocates an underlying array
of size 10 and returns a slice of length 0 and capacity 10 that is
backed by this underlying array.
Map: An empty map is allocated with enough space to hold the
specified number of elements. The size may be omitted, in which case
a small starting size is allocated.
Channel: The channel's buffer is initialized with the specified
buffer capacity. If zero, or the size is omitted, the channel is
unbuffered.
func new(Type) *Type
func make(t Type, size ...IntegerType) Type
new
和 make
的区别package main
import "fmt"
type User struct {
Name string
}
type Addr struct{}
func main() {
user1 := new(User)
user2 := new(User)
fmt.Printf("%#v (%p) %d\n", user1, user1, &user1)
fmt.Printf("%#v (%p) %d\n", user2, user2, &user2)
fmt.Printf("user1 == user2 : %#v\n", user1 == user2)
addr1 := new(Addr)
addr2 := new(Addr)
fmt.Printf("%#v (%p) %d\n", addr1, addr1, &addr1)
fmt.Printf("%#v (%p) %d\n", addr2, addr2, &addr2)
fmt.Printf("addr1 == addr2 : %#v\n", addr1 == addr2)
}
&main.User{Name:""} (0xc00006a250) 824633745448
&main.User{Name:""} (0xc00006a260) 824633745456
user1 == user2 : false
&main.Addr{} (0xf61438) 824633745472
&main.Addr{} (0xf61438) 824633745480
addr1 == addr2 : true
注意上面这一点,空 struct 多次 new 出的指针完全相同。暂时没有想明白这样设计的好处。
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
var
变量const
常量type
类型func
函数go
并发chan
信道select
分支interface
接口map
映射struct
结构体defer
延迟执行goto
跳转return
返回for
continue
break
range
用于读取 slice、map、channel 数据if
else
switch
case
default
fallthrough
package
import
Types:
any bool byte comparable
complex64 complex128 error float32 float64
int int8 int16 int32 int64 rune string
uint uint8 uint16 uint32 uint64 uintptr
Constants:
true false iota
Zero value:
nil
Functions:
append cap close complex copy delete imag len
make new panic print println real recover
true
false
iota
nil
int
int8
int16
int32
int64
uint
uint8
uint16
uint32
uint64
complex64
complex128
float32
float64
byte
=> uint8
rune
=> int32
string
any
comparable
bool
uintptr
指针error
一个内置的 interfaceappend
delete
close
cap
len
copy
make
new
panic
recover
print
println
real
imag
complex
tpl := `[%s] Your verify code is %s.`
s := fmt.Sprintf(tpl, "Markjour", "1234")
println(s)
tpl := `[${sign}] Your verify code is ${code}.`
params := map[string]string{"sign": "Markjour", "code": "1234"}
println(os.Expand(tpl, func(k string) string { return params[k] }))
这两个就可以处理复杂的情况,嵌套模板,控制语句都支持。
package main
import (
"os"
"text/template"
)
func main() {
tpl := `[{{.sign}}] Your verify code is {{.code}}.`
t := template.New("just-a-name")
t, _ = t.Parse(tpl)
params := map[string]string{"sign": "Markjour", "code": "1234"}
t.Execute(os.Stdout, params)
}
strings.Map
/ bytes.Map
提供单个字符的替换func Map(mapping func(rune) rune, s string) string
package main
import (
"fmt"
"strings"
)
const A = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ \n"
const B = "N'|&4:@ j{BI+Y!H/Q_iR\\FM}$moLe?#X\"WCE3S,8(r1f%T.;6DbaG]y`q~ltJxu-k2gA\nvhnd=)*s7Z5p^OK[V0z>9<UcwP"
func main() {
encrypt := func(r rune) rune {
if !strings.ContainsRune(A, r) {
return 0
}
return rune(B[strings.IndexRune(A, r)])
}
decrypt := func(r rune) rune {
if !strings.ContainsRune(B, r) {
return 0
}
return rune(A[strings.IndexRune(B, r)])
}
raw := "Life was like a box of chocolate, you never know what you're gonna get."
fmt.Println(raw)
encrypted := strings.Map(encrypt, raw)
fmt.Println(encrypted)
// 3j:4wFN_wIjB4wNw'!Mw!:w| !|!INi4dw}!RwY4\4QwBY!FwF Niw}!RAQ4w@!YYNw@4i)
decrypted := strings.Map(decrypt, encrypted)
fmt.Println(decrypted)
}
package main
import (
"fmt"
)
type Person struct {
FirstName string
LastName string
}
func main() {
// 准备 =========================
people := make(map[int]Person)
person := Person{
FirstName: "John",
LastName: "Doe",
}
people[1] = person
// 报错:cannot assign to struct field people[1].FirstName in map
// people[1].FirstName = "Jim"
// 方式 1
p := people[1]
p.FirstName = "Alice"
people[1] = p
fmt.Println(people)
// map[1:{Alice Doe}]
fmt.Println(people[1])
// {Alice Doe}
// if p, ok := people[1]; ok {
// p.Field = 5
// people[1] = p
// }
// 方式 2
people2 := make(map[int]*Person)
people2[1] = &person
people2[1].FirstName = "Adam"
fmt.Println(people2)
// map[1:0xc000060020]
fmt.Println(people2[1])
// &{Adam Doe}
}
总之,不能直接通过 key 找到 value(struct),然后修改其中的一个字段。
基础类型:
bool
)string
)复合类型:
[len]Type
)[]Type
)struct
)map[KeyType]ValueType{}
)特殊类型:
*Type
) 指针func
) 函数interface
) 接口chan
) 通道基础类型 + Array + Struct 不是引用类型,其他几种(Slice + Map + Pointer + Function + Interface + Channel)都是引用类型,函数传参的时候需要记住这一点。
uint8 the set of all unsigned 8-bit integers (0 to 255)
uint16 the set of all unsigned 16-bit integers (0 to 65535)
uint32 the set of all unsigned 32-bit integers (0 to 4294967295)
uint64 the set of all unsigned 64-bit integers (0 to 18446744073709551615)
int8 the set of all signed 8-bit integers (-128 to 127)
int16 the set of all signed 16-bit integers (-32768 to 32767)
int32 the set of all signed 32-bit integers (-2147483648 to 2147483647)
int64 the set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807)
float32 the set of all IEEE-754 32-bit floating-point numbers
float64 the set of all IEEE-754 64-bit floating-point numbers
complex64 the set of all complex numbers with float32 real and imaginary parts
complex128 the set of all complex numbers with float64 real and imaginary parts
byte alias for uint8
rune alias for int32
// 实现相关:
uint either 32 or 64 bits
int same size as uint
uintptr an unsigned integer large enough to store the uninterpreted bits of a pointer value
var foo int
var foo int = 1
foo := 1
const foo = 1
const foo int = 1
注意:只有基础类型可以声明为常量。