Skip to content

常量、变量相关题目 #48

Open
@JasonJe

Description

@JasonJe
  1. 判断下面代码能否通过编译
var(
   size := 1024
   max_size = size*2
)

func main() {
    fmt.Println(size,max_size)
}

解析:变量声明的简短形式中,需要使用显示初始化,编译器会自动推导数据类型,所以不需要提供数据类型,只能在函数内部使用简短形式。

  1. iota的使用
const (
    x = iota
    _
    y
    z = "zz"
    k 
    p = iota
)

func main()  {
    fmt.Println(x,y,z,k,p)
}

输出:

0 2 zz zz 5

解析:

  • iota只在常量表达式中使用;

  • 每次 const 出现,都会让const初始化为0

  • 自增常量经常包含一个自定义的枚举类型,允许依靠编译器完成自增设置;

  • 使用 _ 跳过不需要的值;

  • 定义在一行的情况:

const (
    Apple, Banana = iota +1, iota + 2
    Cherimoya, Durian
    Elderberry, Fig
)

上面变量的结果如下:

Apple: 1
Banana: 2
Cherimoya: 2
Durian: 3
Elderberry: 3
Fig: 4
  • 中间插队:
const (
    i = iota
    j = 3.14
    k = iota
    l
) 

上面各个变量对应的结果就是0, 3.14, 2, 3

  1. 下面的赋值是否正确
var x error = nil

解析:nil只能赋值给指针、chanfuncinterfacemapslice

error的定义如下:

type error interface {
    Error() string
}
  1. 下面代码的输出是什么
func hello() []string {  
    return nil
}

func main() {  
    h := hello
    if h == nil {
        fmt.Println("nil")
    } else {
        fmt.Println("not nil")
    }
}

输出:not nil

解析:hhello(),所以其不为空,能通过编译。

  1. iotaconst 关键字
const (
    a = iota
    b = iota
)
const (
    name = "name"
    c    = iota
    d    = iota
)
func main() {
    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(c)
    fmt.Println(d)
}

解析:输出:0 1 1 2iota只能在常量的表达式中使用。iotaconst 关键字出现时将被重置为 0const 中每新增一行常量声明将使 iota 计数一次。

  1. 下面这段代码输出什么
type Direction int

const (
    North Direction = iota
    East
    South
    West
)

func (d Direction) String() string {
    return [...]string{"North", "East", "South", "West"}[d]
}

func main() {
    fmt.Println(South)
}

输出:South

解析:根据 iota 的用法推断出 South 的值是 2;另外,如果类型定义了 String() 方法,当使用 fmt.Printf()fmt.Print()fmt.Println() 会自动使用 String() 方法,实现字符串的打印。

  1. 下面这段代码输出什么
var p *int

func foo() (*int, error) {
    var i int = 5
    return &i, nil
}

func bar() {
    //use p
    fmt.Println(*p)
}

func main() {
    p, err := foo()
    if err != nil {
        fmt.Println(err)
        return
    }
    bar()
    fmt.Println(*p)
}

解析:问题出在操作符:=,对于使用:=定义的变量,如果新变量与同名已定义的变量不在同一个作用域中,那么 Go 会新定义这个变量。对于本例来说,main() 函数里的 p 是新定义的变量,会遮住全局变量 p,导致执行到 bar() 时程序,全局变量 p 依然还是 nil,程序随即 Crash

  1. 下面代码输出什么
func main() {
    i := 1
    s := []string{"A", "B", "C"}
    i, s[i-1] = 2, "Z"
    fmt.Printf("s: %v \n", s)
}

输出:[Z, B, C]

解析:多重赋值时候,上例中,先计算等号左边的索引表达式和取值表达式,接着解读等号右边的表达式,然后进行赋值。所以赋值运算等同于 i, s[0] = 2, "Z"

  1. i++i--Go中是语句,不是表达式,所以不能进行赋值操作。

  2. 下面代码有什么问题

const i = 100
var j = 123

func main() {
    fmt.Println(&j, j)
    fmt.Println(&i, i)
}

结果:编译报错cannot take the address of i

解析:常量不同于变量的在运行期分配内存,常量通常会被编译器在预处理阶段直接展开,作为指令数据使用,所以常量无法寻址。

  1. 下面代码能否通过编译
func GetValue(m map[int]string, id int) (string, bool) {
    if _, exist := m[id]; exist {
        return "exist", true
    }
    return nil, false
}
func main() {
    intmap := map[int]string{
        1: "a",
        2: "b",
        3: "c",
    }

    v, err := GetValue(intmap, 3)
    fmt.Println(v, err)
}

结果:不能通过编译。

解析:nil 可以用作 interfacefunctionpointermapslicechannel 的空值。但是如果不特别指定的话,Go 语言不能识别类型,所以会报错: cannot use nil as type string in return argument.

  1. 下面代码能否通过编译
func Foo(x interface{}) {
    if x == nil {
        fmt.Println("empty interface")
        return
    }
    fmt.Println("non-empty interface")
}
func main() {
    var x *int = nil
    Foo(x)
}

输出:non-empty interface

解析:接口除了有静态类型,还有动态类型和动态值,当且仅当动态值动态类型都为 nil 时,接口类型值才为 nil。这里的 x 的动态类型是 *int,所以 x 不为 nil

  1. 下面代码错误的地方
func main() {

    var s []int
    s = append(s,1)

    var m map[string]int
    m["one"] = 1 
}

解析:不能对 nilmap 直接赋值,需要使用 make() 初始化。但可以使用 append() 函数对为 nilslice 增加元素。

  1. 通过指针变量 p 访问其成员变量 name,有两种方式:p.name(*p).name

  2. 下面的代码有什么问题

func main() {  
    var x = nil 
    _ = x
}

解析:nil 用于表示 interface、函数、mapssliceschannels 的零值。如果不指定变量的类型,编译器猜不出变量的具体类型,导致编译错误。

修复代码:

func main() {
    var x interface{} = nil
    _ = x
}
  1. 下面代码输出什么
func test(x byte)  {
    fmt.Println(x)
}

func main() {
    var a byte = 0x11 
    var b uint8 = a
    var c uint8 = a + b
    test(c)
}

解析:34。与 runeint32 的别名一样,byteuint8 的别名,别名类型无须转换,可直接计算。

  1. 下面代码可以编译通过吗
func main() {
    const x = 123
    const y = 1.23
    fmt.Println(x)
}

解析:编译可以通过。常量是一个简单值的标识符,在程序运行时,不会被修改的量。不像变量,常量未使用是能编译通过的。

  1. 下面代码输出什么
const (
    x uint16 = 120
    y
    s = "abc"
    z
)

func main() {
    fmt.Printf("%T %v\n", y, y)
    fmt.Printf("%T %v\n", z, z)
}

输出:

uint16 120
string abc

解析:常量组中如不指定类型和初始化值,则与上一行非空常量右值相同。

  1. 下面的代码输出什么
func (n N) value(){
    n++
    fmt.Printf("v:%p,%v\n",&n,n)
}

func (n *N) pointer(){
    *n++
    fmt.Printf("v:%p,%v\n",n,*n)
}


func main() {
    var a N = 25

    p := &a
    p1 := &p

    p1.value()
    p1.pointer()
}

结果:编译错误。

calling method value with receiver p1 (type **N) requires explicit dereference
calling method pointer with receiver p1 (type **N) requires explicit dereference

解析:不能使用多级指针调用方法。

Metadata

Metadata

Assignees

No one assigned

    Labels

    GoGolang

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions