{"id":16535788,"url":"https://github.com/yqchilde/golang-interview","last_synced_at":"2025-04-04T10:09:49.666Z","repository":{"id":43037903,"uuid":"225875547","full_name":"yqchilde/Golang-Interview","owner":"yqchilde","description":"Golang面试题，收集自Golang中文网，收集是为了自己可以巩固复习，不必要每次去找","archived":false,"fork":false,"pushed_at":"2023-06-07T15:29:48.000Z","size":161,"stargazers_count":708,"open_issues_count":4,"forks_count":138,"subscribers_count":13,"default_branch":"master","last_synced_at":"2024-10-12T18:28:55.946Z","etag":null,"topics":["go","interview"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yqchilde.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-12-04T13:36:11.000Z","updated_at":"2024-10-08T06:31:35.000Z","dependencies_parsed_at":"2024-10-25T18:28:44.915Z","dependency_job_id":"7647d6f3-c784-4221-a7b1-e04f3df718fa","html_url":"https://github.com/yqchilde/Golang-Interview","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yqchilde%2FGolang-Interview","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yqchilde%2FGolang-Interview/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yqchilde%2FGolang-Interview/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yqchilde%2FGolang-Interview/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yqchilde","download_url":"https://codeload.github.com/yqchilde/Golang-Interview/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247157283,"owners_count":20893220,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","interview"],"created_at":"2024-10-11T18:28:53.101Z","updated_at":"2025-04-04T10:09:49.645Z","avatar_url":"https://github.com/yqchilde.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003e 目录\n\u003e\n\u003e * [1\\. 下面这段代码输出的内容：](#1-%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%E8%BE%93%E5%87%BA%E7%9A%84%E5%86%85%E5%AE%B9)\n\u003e * [2\\. 下面这段代码输出什么，说明原因。](#2-%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%E8%BE%93%E5%87%BA%E4%BB%80%E4%B9%88%E8%AF%B4%E6%98%8E%E5%8E%9F%E5%9B%A0)\n\u003e * [3\\. 下面两段代码输出什么？](#3-%E4%B8%8B%E9%9D%A2%E4%B8%A4%E6%AE%B5%E4%BB%A3%E7%A0%81%E8%BE%93%E5%87%BA%E4%BB%80%E4%B9%88)\n\u003e * [4\\. 下面这段代码有什么缺陷？](#4-%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%E6%9C%89%E4%BB%80%E4%B9%88%E7%BC%BA%E9%99%B7)\n\u003e * [5\\. new() 与 make() 的区别](#5-new-%E4%B8%8E-make-%E7%9A%84%E5%8C%BA%E5%88%AB)\n\u003e * [6\\. 下面这段代码能否通过编译，不能的话原因是什么；如果能，输出什么？](#6-%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%E8%83%BD%E5%90%A6%E9%80%9A%E8%BF%87%E7%BC%96%E8%AF%91%E4%B8%8D%E8%83%BD%E7%9A%84%E8%AF%9D%E5%8E%9F%E5%9B%A0%E6%98%AF%E4%BB%80%E4%B9%88%E5%A6%82%E6%9E%9C%E8%83%BD%E8%BE%93%E5%87%BA%E4%BB%80%E4%B9%88)\n\u003e * [7\\. 下面这段代码能否通过编译，不能的话原因是什么；如果可以，输出什么？](#7%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%E8%83%BD%E5%90%A6%E9%80%9A%E8%BF%87%E7%BC%96%E8%AF%91%E4%B8%8D%E8%83%BD%E7%9A%84%E8%AF%9D%E5%8E%9F%E5%9B%A0%E6%98%AF%E4%BB%80%E4%B9%88%E5%A6%82%E6%9E%9C%E5%8F%AF%E4%BB%A5%E8%BE%93%E5%87%BA%E4%BB%80%E4%B9%88)\n\u003e * [8\\. 下面这段代码能否通过编译，如果可以，输出什么？](#8-%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%E8%83%BD%E5%90%A6%E9%80%9A%E8%BF%87%E7%BC%96%E8%AF%91%E5%A6%82%E6%9E%9C%E5%8F%AF%E4%BB%A5%E8%BE%93%E5%87%BA%E4%BB%80%E4%B9%88)\n\u003e * [9\\. 下面这段代码能否通过编译？不能的话，原因是什么？如果通过，输出什么？](#9%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%E8%83%BD%E5%90%A6%E9%80%9A%E8%BF%87%E7%BC%96%E8%AF%91%E4%B8%8D%E8%83%BD%E7%9A%84%E8%AF%9D%E5%8E%9F%E5%9B%A0%E6%98%AF%E4%BB%80%E4%B9%88%E5%A6%82%E6%9E%9C%E9%80%9A%E8%BF%87%E8%BE%93%E5%87%BA%E4%BB%80%E4%B9%88)\n\u003e * [10\\. 通过指针变量p访问其成员变量name,有哪几种方式？](#10-%E9%80%9A%E8%BF%87%E6%8C%87%E9%92%88%E5%8F%98%E9%87%8Fp%E8%AE%BF%E9%97%AE%E5%85%B6%E6%88%90%E5%91%98%E5%8F%98%E9%87%8Fname%E6%9C%89%E5%93%AA%E5%87%A0%E7%A7%8D%E6%96%B9%E5%BC%8F)\n\u003e * [11\\. 下面这段代码能否通过编译？如果通过，输出什么？](#11-%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%E8%83%BD%E5%90%A6%E9%80%9A%E8%BF%87%E7%BC%96%E8%AF%91%E5%A6%82%E6%9E%9C%E9%80%9A%E8%BF%87%E8%BE%93%E5%87%BA%E4%BB%80%E4%B9%88)\n\u003e * [12\\. 以下代码输出什么？](#12-%E4%BB%A5%E4%B8%8B%E4%BB%A3%E7%A0%81%E8%BE%93%E5%87%BA%E4%BB%80%E4%B9%88)\n\u003e * [13\\. 关于字符串连接，下面语法正确的是？](#13-%E5%85%B3%E4%BA%8E%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%BF%9E%E6%8E%A5%E4%B8%8B%E9%9D%A2%E8%AF%AD%E6%B3%95%E6%AD%A3%E7%A1%AE%E7%9A%84%E6%98%AF)\n\u003e * [14\\. 下面这段代码能否编译通过？如果可以，输出什么？](#14-%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%E8%83%BD%E5%90%A6%E7%BC%96%E8%AF%91%E9%80%9A%E8%BF%87%E5%A6%82%E6%9E%9C%E5%8F%AF%E4%BB%A5%E8%BE%93%E5%87%BA%E4%BB%80%E4%B9%88)\n\u003e * [15\\. 下面赋值正确的是（）](#15-%E4%B8%8B%E9%9D%A2%E8%B5%8B%E5%80%BC%E6%AD%A3%E7%A1%AE%E7%9A%84%E6%98%AF)\n\u003e * [16\\. 关于init函数，下面说法正确的是（）](#16-%E5%85%B3%E4%BA%8Einit%E5%87%BD%E6%95%B0%E4%B8%8B%E9%9D%A2%E8%AF%B4%E6%B3%95%E6%AD%A3%E7%A1%AE%E7%9A%84%E6%98%AF)\n\u003e * [17\\. 下面这段代码输出什么以及原因？](#17-%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%E8%BE%93%E5%87%BA%E4%BB%80%E4%B9%88%E4%BB%A5%E5%8F%8A%E5%8E%9F%E5%9B%A0)\n\u003e * [18\\. 下面这段代码能否编译通过？如果可以，输出什么？](#18-%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%E8%83%BD%E5%90%A6%E7%BC%96%E8%AF%91%E9%80%9A%E8%BF%87%E5%A6%82%E6%9E%9C%E5%8F%AF%E4%BB%A5%E8%BE%93%E5%87%BA%E4%BB%80%E4%B9%88)\n\u003e * [19\\. 关于channel，下面语法正确的是（）](#19-%E5%85%B3%E4%BA%8Echannel%E4%B8%8B%E9%9D%A2%E8%AF%AD%E6%B3%95%E6%AD%A3%E7%A1%AE%E7%9A%84%E6%98%AF)\n\u003e * [20\\. 下面这段代码输出什么？](#20-%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%E8%BE%93%E5%87%BA%E4%BB%80%E4%B9%88)\n\u003e * [21\\. 下面这段代码输出什么？](#21-%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%E8%BE%93%E5%87%BA%E4%BB%80%E4%B9%88)\n\u003e * [22\\. 下面这段代码输出什么？](#22-%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%E8%BE%93%E5%87%BA%E4%BB%80%E4%B9%88)\n\u003e * [23\\. 下面这段代码输出什么？](#23-%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%E8%BE%93%E5%87%BA%E4%BB%80%E4%B9%88)\n\u003e * [24\\. 下面这段代码输出什么？](#24-%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%E8%BE%93%E5%87%BA%E4%BB%80%E4%B9%88)\n\u003e * [25\\. 关于 cap() 函数的适用类型，下面说法正确的是()](#25-%E5%85%B3%E4%BA%8E-cap-%E5%87%BD%E6%95%B0%E7%9A%84%E9%80%82%E7%94%A8%E7%B1%BB%E5%9E%8B%E4%B8%8B%E9%9D%A2%E8%AF%B4%E6%B3%95%E6%AD%A3%E7%A1%AE%E7%9A%84%E6%98%AF)\n\u003e * [26\\. 下面这段代码输出什么？](#26-%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%E8%BE%93%E5%87%BA%E4%BB%80%E4%B9%88)\n\u003e * [27\\. 下面这段代码输出什么？](#27-%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%E8%BE%93%E5%87%BA%E4%BB%80%E4%B9%88)\n\u003e * [28\\. 下面属于关键字的是（）](#28-%E4%B8%8B%E9%9D%A2%E5%B1%9E%E4%BA%8E%E5%85%B3%E9%94%AE%E5%AD%97%E7%9A%84%E6%98%AF)\n\u003e * [29\\. 下面这段代码输出什么？](#29-%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%E8%BE%93%E5%87%BA%E4%BB%80%E4%B9%88)\n\u003e * [30\\. 下面这段代码输出什么？](#30-%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AE%B5%E4%BB%A3%E7%A0%81%E8%BE%93%E5%87%BA%E4%BB%80%E4%B9%88)\n\u003e * [31\\. 31-60题](https://github.com/yqchilde/Golang-Interview/blob/master/31-60.md)\n\n## 1. 下面这段代码输出的内容：\n\n```go\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n    defer_call()\n}\n\nfunc defer_call()  {\n    defer func() {fmt.Println(\"打印前\")}()\n    defer func() {fmt.Println(\"打印中\")}()\n    defer func() {fmt.Println(\"打印后\")}()\n\n    panic(\"触发异常\")\n}\n```\n\n**答：输出内容为：**\n\n```shell\n打印后\n打印中\n打印前\npanic: 触发异常\n```\n\n**解析：**\n`defer` 的执行顺序是先进后出。出现panic语句的时候，会先按照 `defer` 的后进先出顺序执行，最后才会执行panic。\n\n## 2. 下面这段代码输出什么，说明原因。\n\n```go\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n    slice := []int{0, 1, 2, 3}\n    m := make(map[int]*int)\n\n    for key, val := range slice {\n        m[key] = \u0026val\n    }\n\n    for k, v := range m {\n    fmt.Println(k, \"-\u003e\", *v)\n    }\n}\n```\n\n**答：输出内容为：**\n\n```shell\n// 注：key的顺序无法确定\n0 -\u003e 3\n1 -\u003e 3\n2 -\u003e 3\n3 -\u003e 3\n```\n\n**解析：**\n\n`for range` 循环的时候会创建每个元素的副本，而不是每个元素的引用，所以 `m[key] = \u0026val` 取的都是变量val的地址，所以最后 `map` 中的所有元素的值都是变量 `val` 的地址，因为最后 `val` 被赋值为3，所有输出的都是3。\n\n## 3. 下面两段代码输出什么？\n\n```go\n// 1.\nfunc main() {\n    s := make([]int, 5)\n    s = append(s, 1, 2, 3)\n    fmt.Println(s)\n}\n\n// 2.\nfunc main() {\n    s := make([]int, 0)\n    s = append(s, 1, 2, 3, 4)\n    fmt.Println(s)\n}\n```\n\n**答：输出内容为：**\n\n```shell\n// 1.\n[0 0 0 0 0 1 2 3]\n\n// 2.\n[1 2 3 4]\n```\n\n**解析：**\n\n使用 `append` 向 `slice` 中添加元素，第一题中slice容量为5，所以补5个0，第二题为0，所以不需要。\n\n## 4. 下面这段代码有什么缺陷？\n\n```go\nfunc funcMui(x, y int) (sum int, error) {\n    return x + y, nil\n}\n```\n\n**答：第二个返回值没有命名**\n\n**解析：**\n\n在函数有多个返回值时，只要有一个返回值有命名，其他的也必须命名。如果有多个返回值必须加上括号();如果只有一个返回值且命名也需要加上括号()。这里的第一个返回值有命名sum，第二个没有命名，所以错误。\n\n## 5. new() 与 make() 的区别\n\n**解析：**\n\n- `new(T)`  和 `make(T, args)`  是Go语言内建函数，用来分配内存，但适用的类型不用。\n- `new(T)` 会为了 `T` 类型的新值分配已置零的内存空间，并返回地址（指针），即类型为 `*T` 的值。换句话说就是，返回一个指针，该指针指向新分配的、类型为 `T` 的零值。适用于值类型，如 `数组` 、 `结构体` 等。\n- `make(T, args)` 返回初始化之后的T类型的值，也不是指针 `*T` ，是经过初始化之后的T的引用。 `make()` 只适用于 `slice` 、 `map` 和 `channel` 。\n\n## 6. 下面这段代码能否通过编译，不能的话原因是什么；如果能，输出什么？\n\n```go\nfunc main() {\n    list := new([]int)\n    list = append(list, 1)\n    fmt.Println(list)\n}\n```\n\n**答：不能通过**\n\n**解析：**\n\n不能通过编译， `new([]int)` 之后的 `list` 是一个 `*int[]` 类型的指针，不能对指针执行 `append` 操作。可以使用 `make()` 初始化之后再用。同样的， `map` 和 `channel` 建议使用 `make()` 或字面量的方式初始化，不要用 `new` 。 \n\n## 7. 下面这段代码能否通过编译，不能的话原因是什么；如果可以，输出什么？\n\n```go\nfunc main() {\n    s1 := []int{1, 2, 3}\n    s2 := []int{4, 5}\n    s1 = append(s1, s2)\n    fmt.Println(s1)\n}\n```\n\n**答：不能通过**\n\n**解析：**\n\n`append()` 的第二个参数不能直接使用 `slice` ，需使用 `...` 操作符，将一个切片追加到另一个切片上： `append(s1, s2...)` 。或者直接跟上元素，形如： `append(s1, 1, 2, 3)`  。\n\n## 8. 下面这段代码能否通过编译，如果可以，输出什么？\n\n```go\nvar (\n    size := 1024\n    max_size = size * 2\n)\n\nfunc main() {\n    fmt.Println(size, max_size)\n}\n```\n\n**答：不能通过**\n\n**解析：**\n\n这道题的主要知识点是变量的简短模式，形如：x := 100 。但这种声明方式有限制：\n\n1. 必须使用显示初始化；\n1. 不能提供数据类型，编译器会自动推导；\n1. 只能在函数内部使用简短模式；\n\n## 9. 下面这段代码能否通过编译？不能的话，原因是什么？如果通过，输出什么？\n\n```go\nfunc main() {\n    sn1 := struct {\n        age  int\n        name string\n\t}{age: 11, name: \"qq\"}\n\tsn2 := struct {\n        age  int\n        name string\n\t}{age: 11, name: \"11\"}\n\n    if sn1 == sn2 {\n        fmt.Println(\"sn1 == sn2\")\n    }\n\n    sm1 := struct {\n        age int\n        m   map[string]string\n    }{age: 11, m: map[string]string{\"a\": \"1\"}}\n    sm2 := struct {\n        age int\n        m   map[string]string\n    }{age: 11, m: map[string]string{\"a\": \"1\"}}\n\n    if sm1 == sm2 {\n        fmt.Println(\"sm1 == sm2\")\n    }\n}\n```\n\n**答：不能通过,invalid operation: sm1 == sm2**\n\n**解析：**\n\n考点是结构体的比较，有几个需要注意的地方：\n\n1. 结构体只能比较是否相等，但是不能比较大小；\n1. 想同类型的结构体才能进行比较，结构体是否相同不但与属性类型有关，还与属性顺序相关；\n1. 如果struct的所有成员都可以比较，则该struct就可以通过==或!=进行比较是否相同，比较时逐个项进行比较，如果每一项都相等，则两个结构体才相等，否则不相等；\n\n**那有什么是可以比较的呢？**\n\n- 常见的有bool、数值型、字符、指针、数组等\n\n**不能比较的有**\n\n- slice、map、函数\n\n## 10. 通过指针变量p访问其成员变量name,有哪几种方式？\n\n- A. p.name\n- B. (\u0026p).name\n- C. (*p).name\n- D. p-\u003ename\n\n**答：A C**\n\n**解析：**\n\n`\u0026` 取址运算符， `*` 指针解引用\n\n## 11. 下面这段代码能否通过编译？如果通过，输出什么？\n\n```go\npackage main\n\nimport \"fmt\"\n\ntype MyInt1 int\ntype MyInt2 = int\n\nfunc main() {\n    var i int = 0\n    var i1 MyInt1 = i\n    var i2 MyInt2 = i\n    fmt.Println(i1, i2)\n}\n```\n\n**答：不能通过**\n\n**解析：**\n\n这道题考的是 `类型别名` 与 `类型定义` 的区别\n第5行代码是基于类型 `int` 创建了新类型 `MyInt1` ，第6行代码是创建了int的类型别名 `MyInt2` ，注意类型别名的定义是 `=` 。所以，第10行代码相当于是将int类型的变量赋值给MyInt1类型的变量，Go是强类型语言，编译当然不通过；而MyInt2只是int的别名，本质上还是int，可以赋值。\n第10行代码的赋值可以使用强制类型转换 `var i1 MyInt1 = MyInt1(i)` \n\n## 12. 以下代码输出什么？\n\n```go\nfunc main() {\n    a := []int{7, 8, 9}\n    fmt.Printf(\"%+v\\n\", a)\n    ap(a)\n    fmt.Printf(\"%+v\\n\", a)\n    app(a)\n    fmt.Printf(\"%+v\\n\", a)\n}\n\nfunc ap(a []int) {\n    a = append(a, 10)\n}\n\nfunc app(a []int) {\n    a[0] = 1\n}\n```\n\n**答：输出内容为：**\n\n```shell\n[7 8 9]\n[7 8 9]\n[1 8 9]\n```\n\n**解析：**\n\n因为append导致底层数组重新分配内存了，append中的a这个alice的底层数组和外面不是一个，并没有改变外面的。\n\n## 13. 关于字符串连接，下面语法正确的是？\n\n- A. str := 'abc' + '123'\n- B. str := \"abc\" + \"123\"\n- C. str := '123' + \"abc\"\n- D. fmt.Sprintf(\"abc%d\", 123)\n\n**答：B、D**\n\n**解析：**\n\n在Golang中字符串用双引号，字符用单引号\n字符串连接除了以上两种连接方式，还有 `strings.Join()` 、 `buffer.WriteString()` 等\n\n## 14. 下面这段代码能否编译通过？如果可以，输出什么？\n\n```go\nconst (\n    x = iota\n    _\n    y\n    z = \"zz\"\n    k\n    p = iota\n)\n\nfunc main() {\n    fmt.Println(x, y, z, k, p)\n}\n```\n\n**答：编译通过，输出：**`**0 2 zz zz 5**` \n\n**解析：**\n\niota初始值为0，所以x为0，_表示不赋值，但是iota是从上往下加1的，所以y是2，z是“zz”,k和上面一个同值也是“zz”,p是iota,从上0开始数他是5\n\n## 15. 下面赋值正确的是（）\n\n- A. var x = nil\n- B. var x interface{} = nil\n- C. var x string = nil\n- D. var x error = nil\n\n**答：B、D**\n\n**解析：**\n\nA错在没有写类型，C错在字符串的空值是 `\"\"` 而不是nil。\n知识点：nil只能赋值给指针、chan、func、interface、map、或slice、类型的变量。\n\n## 16. 关于init函数，下面说法正确的是（）\n\n- A. 一个包中，可以包含多个init函数；\n- B. 程序编译时，先执行依赖包的init函数，再执行main包内的init函数；\n- C. main包中，不能有init函数；\n- D. init函数可以被其他函数调用；\n\n**答：A、B**\n\n**解析：**\n\n1. init()函数是用于程序执行前做包的初始化的函数，比如初始化包里的变量等；\n1. 一个包可以出现多个init()函数，一个源文件也可以包含多个init()函数；\n1. 同一个包中多个init()函数的执行顺序没有明确的定义，但是不同包的init函数是根据包导入的依赖关系决定的；\n1. init函数在代码中不能被显示调用、不能被引用（赋值给函数变量），否则出现编译失败；\n1. 一个包被引用多次，如A import B，C import B，A import C，B被引用多次，但B包只会初始化一次；\n1. 引入包，不可出现死循环。即A import B，B import A，这种情况下编译失败；\n\n![image.png](https://cdn.nlark.com/yuque/0/2019/png/517869/1574040068413-cfcc17c2-6f8b-4c1c-b09b-d6d297c9f745.png#align=left\u0026display=inline\u0026height=330\u0026name=image.png\u0026originHeight=419\u0026originWidth=948\u0026size=156149\u0026status=done\u0026width=746)\n\n\n## 17. 下面这段代码输出什么以及原因？\n\n```go\nfunc hello() []string {\n    return nil\n}\n\nfunc main() {\n    h := hello\n    if h == nil {\n        fmt.Println(\"nil\")\n    } else {\n        fmt.Println(\"not nil\")\n    }\n}\n```\n\n- A. nil\n- B. not nil\n- C. compilation error\n\n**答：B**\n\n**解析：**\n\n这道题里面，是将 `hello()` 赋值给变量h，而不是函数的返回值，所以输出 `not nil` \n\n## 18. 下面这段代码能否编译通过？如果可以，输出什么？\n\n```go\nfunc GetValue() int {\n    return 1\n}\n\nfunc main() {\n    i := GetValue()\n    switch i.(type) {\n    case int:\n        fmt.Println(\"int\")\n    case string:\n        fmt.Println(\"string\")\n    case interface{}:\n        fmt.Println(\"interface\")\n    default:\n        fmt.Println(\"unknown\")\n    }\n}\n```\n\n**答：编译失败**\n\n**解析：**\n\n只有接口类型才能使用类型选择\n类型选择的语法形如：i.(type)，其中i是接口，type是固定关键字，需要注意的是，只有接口类型才可以使用类型选择。\n\n## 19. 关于channel，下面语法正确的是（）\n\n- A. var ch chan int\n- B. ch := make(chan int)\n- C. \u003c-ch\n- D. ch\u003c-\n\n**答：A、B、C**\n\n**解析：**\n\nA、B都是申明channel；C读取channel；写channel是必须带上值，所以D错误。\n\n## 20. 下面这段代码输出什么？\n\n- A. 0\n- B. 1\n- C. Compilation error\n\n```go\ntype person struct {\n    name string\n}\n\nfunc main() {\n    var m map[person]int\n    p := person{\"make\"}\n    fmt.Println(m[p])\n}\n```\n\n**答：A**\n\n**解析：**\n\n打印一个map中不存在的值时，返回元素类型的零值。这个例子中，m的类型是map[person]int，因为m中 不存在p，所以打印int类型的零值，即0。\n\n## 21. 下面这段代码输出什么？\n\n- A. 18\n- B. 5\n- C. Compilation error\n\n```go\nfunc hello(num ...int) {\n    num[0] = 18\n}\n\nfunc main() {\n    i := []int{5, 6, 7}\n    hello(i...)\n    fmt.Println(i[0])\n}\n```\n\n**答：18**\n\n**解析：**\n\n可变参数传递过去，改变了第一个值。\n\n## 22. 下面这段代码输出什么？\n\n```go\nfunc main() {  \n    a := 5\n    b := 8.1\n    fmt.Println(a + b)\n}\n```\n\n- A. 13.1  \n- B. 13\n- C. compilation error  \n\n**答：C**\n\n**解析：**\n\n`a` 的类型是`int` ，`b` 的类型是`float` ，两个不同类型的数值不能相加，编译报错。\n\n## 23. 下面这段代码输出什么？\n\n```go\npackage main\n\nimport (  \n    \"fmt\"\n)\n\nfunc main() {  \n    a := [5]int{1, 2, 3, 4, 5}\n    t := a[3:4:4]\n    fmt.Println(t[0])\n}\n```\n\n- A. 3\n- B. 4\n- C. compilation error  \n\n**答：B**\n\n**解析：**\n\n- 知识点：操作符 `[i, j]`。基于数组（切片）可以使用操作符 `[i, j]`创建新的切片，从索引 `i` ，到索引 `i` ，到索引 `j` 结束，截取已有数组（切片）的任意部分，返回新的切片，新切片的值包含原数组（切片）的 `i` 索引的值，但是不包含 `j` 索引的值。`i` 、`j` 都是可选的，`i` 如果省略，默认是0，`j` 如果省略，默认是原数组（切片）的长度。`i` 、`j` 都不能超过这个长度值。\n\n- 假如底层数组的大小为 k，截取之后获得的切片的长度和容量的计算方法：**长度：j-i，容量：k-i**。\n\n  截取操作符还可以有第三个参数，形如 [i,j,k]，第三个参数 k 用来限制新切片的容量，但不能超过原数组（切片）的底层数组大小。截取获得的切片的长度和容量分别是：**j-i、k-i**。\n\n  所以例子中，切片 t 为 [4]，长度和容量都是 1。\n\n## 24. 下面这段代码输出什么？\n\n```go\nfunc main() {\n    a := [2]int{5, 6}\n    b := [3]int{5, 6}\n    if a == b {\n        fmt.Println(\"equal\")\n    } else {\n        fmt.Println(\"not equal\")\n    }\n}\n```\n\n- A. compilation error  \n- B. equal  \n- C. not equal \n\n**答：A**\n\n**解析：**\n\nGo中的数组是值类型，可比较，另外一方面，数组的长度也是数组类型的组成部分，所以 `a` 和 `b` 是不同的类型，是不能比较的，所以编译错误。\n\n## 25. 关于 cap() 函数的适用类型，下面说法正确的是()\n\n- A. array\n- B. slice\n- C. map\n- D. channel\n\n**答：A、B、D**\n\n**解析：**\n\ncap()，cap() 函数不适用 map\n\n## 26. 下面这段代码输出什么？\n\n```go\nfunc main() {  \n    var i interface{}\n    if i == nil {\n        fmt.Println(\"nil\")\n        return\n    }\n    fmt.Println(\"not nil\")\n}\n```\n\n- A. nil\n- B. not nil\n- C. compilation error  \n\n**答：A**\n\n**解析：**\n\n当且仅当接口的动态值和动态类型都为 nil 时，接口类型值才为 nil\n\n## 27. 下面这段代码输出什么？\n\n```go\nfunc main() {  \n    s := make(map[string]int)\n    delete(s, \"h\")\n    fmt.Println(s[\"h\"])\n}\n```\n\n- A. runtime panic\n- B. 0\n- C. compilation error \n\n**答：B**\n\n**解析：**\n\n删除 map 不存在的键值对时，不会报错，相当于没有任何作用；获取不存在的减值对时，返回值类型对应的零值，所以返回 0。\n\n## 28. 下面属于关键字的是（）\n\n- A. func\n- B. struct\n- C. class\n- D. defer\n\n**答：A、B、D**\n\n## 29. 下面这段代码输出什么？\n\n```go\nfunc main() {  \n    i := -5\n    j := +5\n    fmt.Printf(\"%+d %+d\", i, j)\n}\n```\n\n- A. -5 +5\n- B. +5 +5\n- C. 0  0\n\n**答：A**\n\n**解析：**\n\n`%d`表示输出十进制数字，`+`表示输出数值的符号。这里不表示取反。\n\n## 30. 下面这段代码输出什么？\n\n```go\ntype People struct{}\n\nfunc (p *People) ShowA() {\n    fmt.Println(\"showA\")\n    p.ShowB()\n}\nfunc (p *People) ShowB() {\n    fmt.Println(\"showB\")\n}\n\ntype Teacher struct {\n    People\n}\n\nfunc (t *Teacher) ShowB() {\n    fmt.Println(\"teacher showB\")\n}\n\nfunc main() {\n    t := Teacher{}\n    t.ShowB()\n}\n```\n\n**答：teacher showB**\n\n**解析：**\n\n知识点：结构体嵌套。\n\n在嵌套结构体中，People 称为内部类型，Teacher 称为外部类型；通过嵌套，内部类型的属性、方法，可以为外部类型所有，就好像是外部类型自己的一样。此外，外部类型还可以定义自己的属性和方法，甚至可以定义与内部相同的方法，这样内部类型的方法就会被“屏蔽”。这个例子中的 ShowB() 就是同名方法。\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyqchilde%2Fgolang-interview","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyqchilde%2Fgolang-interview","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyqchilde%2Fgolang-interview/lists"}