导包和声明

当包名重复时

如果我们想同时导入两个有着名字相同的包,例如math/rand包和crypto/rand包,那么导入声明必须至少为一个同名包指定一个新的包名以避免冲突。这叫做导入包的重命名。

import (
    "crypto/rand"
    mrand "math/rand" // alternative name mrand avoids conflict
)

导入包的重命名只影响当前的源文件。其它的源文件如果导入了相同的包,可以用导入包原本默认的名字或重命名为另一个完全不同的名字。

包的匿名导入

如果只是导入一个包而并不使用导入的包将会导致一个编译错误。但是有时候我们只是想利用导入包而产生的副作用:它会计算包级变量的初始化表达式和执行导入包的init初始化函数。这时候我们需要抑制“unused import”编译错误,我们可以用下划线_来重命名导入的包。像往常一样,下划线_为空白标识符,并不能被访问。

import _ "image/png" // register PNG decoder

这个被称为包的匿名导入。它通常是用来实现一个编译时机制,然后通过在main主程序入口选择性地导入附加的包。首先,让我们看看如何使用该特性,然后再看看它是如何工作的。

标准库的image图像包包含了一个Decode函数,用于从io.Reader接口读取数据并解码图像,它调用底层注册的图像解码器来完成任务,然后返回image.Image类型的图像。使用image.Decode很容易编写一个图像格式的转换工具,读取一种格式的图像,然后编码为另一种图像格式:

package main

import (
        "fmt"
        "image"
        "image/jpeg"
        _ "image/png"
        "io"
        "os"
)

func main() {

        if len(os.Args) < 3 {
                fmt.Println("using ./   aaa.png bbb.jpg")
        }

        inFilename := os.Args[1]
        outFilename := os.Args[2]

        infile, err := os.Open(inFilename)
        if err != nil {
                fmt.Println(err)
                return
        }
        defer infile.Close()

        outfile, err := os.Create(outFilename)
        if err != nil {
                fmt.Println(err)
                return
        }
        defer outfile.Close()

        toJPEG(infile, outfile)

}

func toJPEG(in io.Reader, out io.Writer) error {
        //将传递进来的文件解码
        img, kind, err := image.Decode(in)
        if err != nil {
                return err
        }

        fmt.Fprintln(os.Stderr, "Input format = ", kind)

        return jpeg.Encode(out, img, &jpeg.Options{Quality: 95})
}

因为jpeg会用到png格式,但是我们的代码并没有用到,所以如果不import image/png,编译没有问题,但是不会生成png图片,

要是import image/png则会被编译器告知,没有使用这个包而报错,所以就只有使用匿名的import方式。

results matching ""

    No results matching ""