> For the complete documentation index, see [llms.txt](https://wskdsgcf.gitbook.io/mastering-go-zh-cn/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wskdsgcf.gitbook.io/mastering-go-zh-cn/12.0/12.6.md).

# 12.6 实现DNS查询

DNS全称**Domain Name System（域名系统）**，它的作用是将IP地址转换为类似`packt.com`的域名，或者将域名转换为IP地址。本节中开发的`DNS.go`程序的处理逻辑非常简单：如果程序执行时的命令行参数是一个有效的IP地址，则程序将查询该IP地址对应的主机名；其他情况下，程序将假定它处理的是一个主机名，并将其转换成一个或多个IP地址。

程序`DNS.go`的代码将分三部分介绍。第一部分程序包含以下Go代码：

> ```go
> package main
>
> import (
>     "fmt"
>     "net"
>     "os"
> )
>
> func lookIP(address string) ([]string, error) {
>     hosts, err := net.LookupAddr(address)
>     if err != nil {
>         return nil, err
>     }
>     return hosts, nil
> }
>
> func lookHostname(hostname string) ([]string, error) {
>     IPs, err := net.LookupHost(hostname)
>     if err != nil {
>         return nil, err
>     }
>     return IPs, nil
> }
> ```

函数`lookIP()`将一个IP地址作为输入，然后返回与该IP地址匹配的主机列表，这个功能通过函数`net.LookupAddr()`的帮助来实现。

而函数`lookHostname()`将主机名作为输入，使用`net.LookupHost()`函数进行处理，返回一个相关IP地址的列表。

程序`DNS.go`的第二部分是以下Go代码：

> ```go
> func main() {
>     arguments := os.Args
>     if len(arguments) == 1 {
>         fmt.Println("Please provide an argument!")
>         return
>     }
>
>     input := arguments[1]
>     IPaddress := net.ParseIP(input)
> ```

函数`net.ParseIP()`可以将输入字符串解析为IPv4或IPv6地址。如果输入一个非法的IP地址，函数`net.ParseIP()`将返回`nil`。

程序`DNS.go`的剩余Go代码如下：

> ```go
>     if IPaddress == nil {
>         IPs, err := lookHostname(input)
>         if err == nil {
>             for _, singleIP := range IPs {
>                 fmt.Println(singleIP)
>             }
>         }
>     } else {
>         hosts, err := lookIP(input)
>         if err == nil {
>             for _, hostname := range hosts {
>                 fmt.Println(hostname)
>             }
>         }
>     }
> }
> ```

执行`DNS.go`程序，并携带不同的输入参数，将生成以下输出：

> ```
> $ go run DNS.go 127.0.0.1
> localhost
> $ go run DNS.go 192.168.1.1
> cisco
> $ go run DNS.go packtpub.com
> 83.166.169.231
> $ go run DNS.go google.com
> 2a00:1450:4001:816::200e
> 216.58.210.14
> $ go run DNS.go www.google.com
> 2a00:1450:4001:816::2004
> 216.58.214.36
> $ go run DNS.go cnn.com
> 2a04:4e42::323
> 2a04:4e42:600::323
> 2a04:4e42:400::323
> 2a04:4e42:200::323
> 151.101.193.67
> 151.101.1.67
> 151.101.129.67
> 151.101.65.67
> ```

可以看到`go run DNS.go 192.168.1.1`命令的输出来自`/etc/hosts`文件，因为在`/etc/hosts`文件中配置了IP地址`192.168.1.1`的别名`cisco`。

最后一个命令的输出演示了域名（`cnn.com`）可能有多个公网IP地址映射。请特别注意*公网*这个词，尽管`www.google.com`有多个IP地址，但是只有地址（`216.58.214.36`）是公网IP地址。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://wskdsgcf.gitbook.io/mastering-go-zh-cn/12.0/12.6.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
