Golang Tour练习问题探讨

Golang Tour练习问题探讨 我在完成Go语言之旅的这个练习时,遇到了代码无法运行的问题:

https://tour.golang.org/moretypes/18

主函数的调用只是运行了:pic.Show(Pic)。这是问题的一部分吗?既然Pic函数接受两个参数,那么它应该运行类似pic.Show(Pic(3,3))这样的代码才对?

当然,我已经尝试运行这段代码,但它失败了,所以我的代码也有问题。但我的代码非常简单,我不明白它怎么会出错,而且错误信息也帮不上忙:

    package main
    import "golang.org/x/tour/pic"

    func Pic(dx, dy int) [][]uint8 {

    	output := [][]uint8{
    		[]uint8{0, 0, 0},
    		[]uint8{0, 255, 0},
    		[]uint8{0, 0, 0},
    	}

    	return output
    }

    func main() {
    	pic.Show(Pic)
    }

panic: runtime error: index out of range [3] with length 3

goroutine 1 [running]: golang.org/x/tour/pic.Show(0x4eea60)

  • /tmp/gopath773663214/pkg/mod/golang.org/x/tour@v0.0.0-20210305160921-b3263fcf7749/pic/pic.go:36 +0x1a6* main.main()
  • /tmp/sandbox350473227/prog.go:27 +0x2d*

更多关于Golang Tour练习问题探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

我想我已经回答了自己的问题。pic.Show 需要一个返回 [][]uint8 的函数,而不是 [3][3]uint8。考虑到这一点,我认为我之前要么是返回了一个返回 [3][3]uint8 的函数,要么就是直接返回了 [3][3]uint8,这两种情况都不对(我认为这就是“index out of range [3] with length 3”试图告诉我的信息)。

话虽如此,这仍然有点令人困惑,因为我仍然编写了一个返回有界数组的函数,但这个界限是由传递给函数的参数决定的。我仍然希望能了解为什么我的第一次尝试没有仅仅绘制一个 3x3 像素的正方形。

我的最终解决方案是:

package main

import "golang.org/x/tour/pic"

func Pic(dx, dy int) [][]uint8 {

	var output [][]uint8

	for len(output) < dy {
		output = append(output, make([]uint8, dx))
	}

	for y:=0 ; y<dy; y++ {
		for x:=0 ; x<dx; x++ {
			output[y][x] = uint8((x+y))
		}
	}

	return output
}

func main() {
	pic.Show(Pic)
}

更多关于Golang Tour练习问题探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这是一个典型的类型不匹配问题。pic.Show期望接收一个函数,该函数接受两个int参数并返回[][]uint8,但你的Pic函数返回的切片维度与传入的dx, dy参数不匹配。

错误信息显示索引越界,因为pic.Show内部会使用你提供的dx, dy值(比如256x256)来调用你的Pic函数,然后尝试访问返回的切片。但你的函数总是返回固定的3x3切片,当dxdy大于3时就会导致越界。

正确的实现应该根据传入的dx, dy参数动态创建切片:

package main

import "golang.org/x/tour/pic"

func Pic(dx, dy int) [][]uint8 {
    // 创建dy行的切片
    pic := make([][]uint8, dy)
    
    for y := range pic {
        // 每行创建dx列的切片
        pic[y] = make([]uint8, dx)
        for x := range pic[y] {
            // 这里设置每个像素的值
            // 例如:(x+y)/2, x*y, x^y 等
            pic[y][x] = uint8((x + y) / 2)
        }
    }
    
    return pic
}

func main() {
    pic.Show(Pic)
}

或者使用更简洁的写法:

func Pic(dx, dy int) [][]uint8 {
    pic := make([][]uint8, dy)
    for y := 0; y < dy; y++ {
        row := make([]uint8, dx)
        for x := 0; x < dx; x++ {
            row[x] = uint8(x * y)  // 或者 uint8(x^y), uint8((x+y)/2) 等
        }
        pic[y] = row
    }
    return pic
}

pic.Show(Pic)的调用是正确的,因为pic.Show期望接收一个函数(函数值),而不是函数的调用结果。它会内部使用测试用的dx, dy值来调用你的Pic函数。

回到顶部