Эта статьяЭти ямы в языке Goдва.
В Golang функции рассматриваются как значения, а значения функций нельзя сравнивать или использовать в качестве ключей карты.
Можно ли скомпилировать следующий код?
import (
"fmt"
)
func main(){
array := make(map[int]func ()int)
array[func()int{ return 10}()] = func()int{
return 12
}
fmt.Println(array)
}```
**答案:**
Его можно нормально скомпилировать.
稍作改动,改为如下的情况,还能编译通过吗?
```Go
import (
"fmt"
)
func main(){
array := make(map[func ()int]int)
array[func()int{return 12}] = 10
fmt.Println(array)
}```
**答案:**
Не могу скомпилировать.
在Go语言中,函数被看做是第一类值:(first-class values):函数和其他值一样,可以被赋值,可以传递给函数,可以从函数返回。也可以被当做是一种“函数类型”。例如:有函数``func square(n int) int { return n * n }``,那么就可以赋值``f := square``,而且还可以``fmt.Println(f(3))``(将打印出“9”)。
Go语言函数有两点很特别:
+ 函数值类型不能作为map的key
+ 函数值之间不可以比较,函数值只可以和nil作比较,函数类型的零值是``nil``
# 匿名函数作用域陷阱
请看下列代码输出什么?
```Go
import (
"fmt"
)
func main(){
var msgs []func()
array := []string{
"1", "2", "3", "4",
}
for _, e := range array{
msgs = append(msgs, func(){
fmt.Println(e)
})
}
for _, v := range msgs{
v()
}
}
Отвечать:
4
4
4
4
В приведенном выше коде в анонимную функцию записывается адрес памяти переменной цикла, а не значение переменной цикла в определенный момент.
Если вы хотите вывести 1, 2, 3 и 4, вам нужно изменить на:
import (
"fmt"
)
func main(){
var msgs []func()
array := []string{
"1", "2", "3", "4",
}
for _, e := range array{
elem := e
msgs = append(msgs, func(){
fmt.Println(elem)
})
}
for _, v := range msgs{
v()
}
}
Фактически добавленоelem := e
Это кажется избыточным, но это не так.Таким образом, после каждого цикла локальные переменные, сохраненные в каждой анонимной функции, все в это время.elem
Значение , такие локальные переменные определены 4, каждый раз, когда цикл генерирует один.
[3]int
а также[4]int
не тот тип
Пожалуйста, взгляните на код и спросите выводtrue
все ещеfalse
import (
"fmt"
"reflect"
)
func main(){
arrayA := [...]int{1, 2, 3}
arrayB := [...]int{1, 2, 3, 4}
fmt.Println(reflect.TypeOf(arrayA) == reflect.TypeOf(arrayB))
}
ответ:
false
Длина массива является компонентом типа массива, поэтому [3]int и [4]int — это два разных типа массивов.
Массивы также можно инициализировать, указав индекс и соответствующее значение.
Например:
import (
"fmt"
)
func main(){
arrayA := [...]int{0:1, 2:1, 3:4}
fmt.Println(arrayA)
}
выведет:
[1 0 1 4]
Немного какPHP
Ощущение массива, но не то:arrayA
Какова его длина?
import (
"fmt"
)
func main(){
arrayA := [...]int{0:1, 2:1, 3:4}
fmt.Println(len(arrayA))
}
ответ:
4
Правильно, определен массив с длиной массива 4, и длина массива указанного индекса связана со значением последнего индекса, например:r := [...]int{99:-1}
определяет массив из 100 элементовr
, выход последнего элемента равен -1, а остальные элементы инициализируются 0.
Не удается обратиться к элементу на карте&
действовать
a := &ages["bob"] // compile error: cannot take address of map element
Элемент в карте не является переменной, и адресная операция не может быть выполнена над элементами карты.Причина, по которой адресная операция на карте запрещена, может заключаться в том, что карта может перераспределить пространство памяти как число элементов увеличивается, что приведет к тому, что исходный адрес станет недействительным.
Когда карта равна нулю, значение не может быть добавлено
func main() {
var sampleMap map[string]int
sampleMap["test"] = 1
fmt.Println(sampleMap)
}
Ошибка вывода:
panic: assignment to entry in nil map
Вы должны использовать make или инициализировать карту перед добавлением элементов.
Приведенный выше код можно изменить на:
func main() {
var sampleMap map[string]int
sampleMap = map[string]int {
"test1":1,
}
sampleMap["test"] = 1
fmt.Println(sampleMap)
}
может правильно вывести:
map[test1:1 test:1]
&dilbert.Position
а также(&dilbert).Position
это отличается
&dilbert.Position
эквивалентно&(dilbert.Position)
вместо(&dilbert).Position
См. пример:
Подскажите, пожалуйста, что на выходе?
func main(){
type Employee struct {
ID int
Name string
Address string
DoB time.Time
Position string
Salary int
ManagerID int
}
var dilbert Employee
dilbert.Position = "123"
position := &dilbert.Position
fmt.Println(position)
}
вывод:
0xc42006c220
Выход - адрес памяти
изменить его, поставить&dilbert.Position
изменить на(&dilbert).Position
func main(){
type Employee struct {
ID int
Name string
Address string
DoB time.Time
Position string
Salary int
ManagerID int
}
var dilbert Employee
dilbert.Position = "123"
position := &dilbert.Position
fmt.Println(position)
}
вывод:
123
Когда функция возвращает значение на языке Go, ей нельзя присвоить значение
См. пример ниже:
type Employee struct {
ID int
Name string
Address string
DoB time.Time
Position string
Salary int
ManagerID int
}
func EmployeeByID(id int) Employee {
return Employee{ID:id}
}
func main(){
EmployeeByID(1).Salary = 0
}
Может ли он быть скомпилирован?
запустить, ошибка вывода:cannot assign to EmployeeByID(1).Salary
В этом примере функцияEmployeeById(id int)
Возвращаемое значение имеет тип, его значениеEmployeeByID(1).Salary
Это также тип значения; какова концепция типа значения? Типы значений и операторы присваиванияvar a = 1
илиvar a = hello world
знак равенства=
правая сторона1
,Hello world
Является концептом, его нельзя назначать, можно назначать только переменные.
Процедура модификации следующая:
type Employee struct {
ID int
Name string
Address string
DoB time.Time
Position string
Salary int
ManagerID int
}
func EmployeeByID(id int) Employee {
return Employee{ID:id}
}
func main(){
var a = EmployeeByID(1)
a.Salary = 0
}
Это компилирует
При объявлении метода, если имя типа само по себе является указателем, оно не может появляться в получателе метода.
Пожалуйста, посмотрите следующий пример, будет ли он скомпилирован и пройден?
import (
"fmt"
)
type littleGirl struct{
Name string
Age int
}
type girl *littleGirl
func(this girl) changeName(name string){
this.Name = name
}
func main(){
littleGirl := girl{Name:"Rose", Age:1}
girl.changeName("yoyo")
fmt.Println(littleGirl)
}
Отвечать:
不能编译通过,会提示“invalid receiver type girl(girl is a pointer type)”
Язык Go предусматривает, что только тип (Type) и указатель на них (*Type) являются двумя получателями, которые могут фигурировать в объявлении получателя Во избежание двусмысленности четко оговорено, что если само имя типа является указатель не допускается в приемнике.
Функции допускают nil указатели в качестве аргументов и nil в качестве приемников методов.
Пожалуйста, посмотрите следующий пример, можете ли вы его скомпилировать?
import (
"fmt"
)
type littleGirl struct{
Name string
Age int
}
func(this littleGirl) changeName(name string){
fmt.Println(name)
}
func main(){
little := littleGirl{Name:"Rose", Age:1}
little = nil
little.changeName("yoyo")
fmt.Println(little)
}
Отвечать:
不能编译通过,显示"cannot use nil as type littleGirl in assignment"
В Go методы могут принимать нулевые указатели в качестве приемников, а функции могут принимать нулевые указатели в качестве параметров. И в приведенном выше кодеlittleGirl
не является типом указателя, измените его на*littleGirl
, то переменнаяlittle
назначить как&littleGirl{Name:"Rose", Age:1}
Его можно скомпилировать и передать.
Кроме того, когда nil является допустимым нулевым значением для объекта, такого как карта или фрагмент, он компилируется и работает нормально.
Форматирование времени в Голанге
отличается от PHPdate("Y-m-d H:i:s", time())
, формат Golang очень странный, вы не можете использовать такие вещи, какY-m-d H:i:s
что-то, но использовать2006-01-02 15:04:05
Формат этого времени, пожалуйста, помните это время, говорят, что это время рождения Голанга.
time := time.Now()
time.Format("20060102") //相当于Ymd
time.Format("2006-01-02")//相当于Y-m-d
time.Format("2006-01-02 15:04:05")//相当于Y-m-d H:i:s
time.Format("2006-01-02 00:00:00")//相当于Y-m-d 00:00:00