Golang: 在发送文本文件中的项目查询时出现“函数末尾缺少返回”

huangapple go评论73阅读模式
英文:

Golang: "missing return at end of function" when sending queries for item in text file

问题

我有这样一段代码,其中我在文本文件的每一行发送GET请求。然而,当我尝试运行代码时,我收到一个错误,提示“函数末尾缺少返回”。我知道这很可能是因为我在最后一个括号之前返回了它,但是我需要该括号内的代码,因为它定义了行、请求和正文内容。

我的代码:

// 程序入口
func main() {
    rep := 1000
    results := make(chan string)

    for i := 0; i < rep; i++ {
        go func(num int) {
            results <- request(num)
        }(i)
    }

    for i := 0; i < rep; i++ {
        fmt.Println(<-results)
    }
}

func request(num int) string {
    // 读取 names.txt 文件中的每一行
    wordlist, err := readLines("assets/names.txt")
    if err != nil {
        log.Fatalf("readLines: %s", err)
    }
    for _, line := range wordlist {
        // 发送请求
        response, err := http.Get("https://accounts.com/" + line + "/userId")
        if err != nil {
            fmt.Printf("%s", err)
        }

        defer response.Body.Close()
        contents, err := ioutil.ReadAll(response.Body)
        if err != nil {
            fmt.Printf("%s", err)
            os.Exit(1)
        }
        fmt.Printf("%s\n", string(contents))
        return string(contents)
    }
}

请注意,我只翻译了代码部分,其他内容不包括在内。

英文:

I have this code where I send get requests per line in a text file. However, when I'm trying to run the code I get an error saying "missing return at end of function". I know that this is most likely due to the fact that I'm returning it before the final bracket, but I need the code within that bracket as It's defining the lines, the requests and the body content.

My code:

// Routine
func main() {
    rep := 1000
    results := make(chan string)

    for i := 0; i &lt; rep; i++ {
        go func(num int) {
            results &lt;- request(num)
        }(i)
    }

    for i := 0; i &lt; rep; i++ {
        fmt.Println(&lt;-results)
    }
}

func request(num int) string {
    // For name in names.txt
	wordlist, err := readLines(&quot;assets/names.txt&quot;)
	if err != nil {
		log.Fatalf(&quot;readLines: %s&quot;, err)
	}
	for _, line := range wordlist {
        // Send request
		response, err := http.Get(&quot;https://accounts.com/&quot; + line + &quot;/userId&quot;)
		if err != nil {
			fmt.Printf(&quot;%s&quot;, err)
		}

		defer response.Body.Close()
		contents, err := ioutil.ReadAll(response.Body)
		if err != nil {
		  fmt.Printf(&quot;%s&quot;, err)
		  os.Exit(1)
		}
		fmt.Printf(&quot;%s\n&quot;, string(contents))
		return string(contents) 
	}
}

答案1

得分: 1

根据Go编程语言规范的规定:

如果函数的签名声明了结果参数,函数体的语句列表必须以终止语句结尾。

为了帮助解释这个问题,我们可以将您的代码简化为:

package main

import "fmt"

func main() {
	fmt.Println(request([]string{"foo"}))
}

func request(wordlist []string) string {
	for _, line := range wordlist {
		// 做一些操作
		return line
	}
}

可以通过在循环后面添加一个返回语句来修复错误:

package main

import "fmt"

func main() {
	fmt.Println(request([]string{"foo"}))
}

func request(wordlist []string) string {
	for _, line := range wordlist {
		// 做一些操作
		return line
	}
	return ""
}

需要添加额外的return语句的原因是因为函数可能会传递一个空的切片。在这种情况下,for循环内的代码永远不会执行,意味着没有终止语句(请注意,您可以用panic替换return)。如果readLines返回一个空的切片,您的代码也会出现相同的情况。

值得注意的是,在这里使用循环并没有太多意义,因为您似乎只对第一个值感兴趣。您可以使用类似的方法实现相同的结果

package main

import "fmt"

func main() {
	fmt.Println(request([]string{"foo", "boo"}))
	fmt.Println(request(nil))
}

func request(wordlist []string) string {
	if len(wordlist) == 0 {
		return "No Data"
	}

	line := wordlist[0]
	// 做一些操作...
	return line
}

我猜您实际上想处理所有的行,但很遗憾,您的问题没有提供足够的上下文来进一步帮助。

英文:

As per the Go Programming Language Specification

>If the function's signature declares result parameters, the function body's statement list must end in a terminating statement.

To assist in explaining the issue we can simplify your code to:

package main

import &quot;fmt&quot;

func main() {
	fmt.Println(request([]string{&quot;foo&quot;}))
}

func request(wordlist []string) string {
	for _, line := range wordlist {
		// Do something
		return line
	}
}

The error can be fixed by adding a return after the loop:

package main

import &quot;fmt&quot;

func main() {
	fmt.Println(request([]string{&quot;foo&quot;}))
}

func request(wordlist []string) string {
	for _, line := range wordlist {
		// Do something
		return line
	}
	return &quot;&quot;
}

The reason that the extra return is needed is because the function could be passed an empty slice. In that case the code within the for is never executed meaning that there is no terminating statement (note that you could replace the return with a panic). The same applies in your code if readLines returns an empty slice.

I think it's worth noting that using a loop here does not make a lot of sense because you appear to only be interested in the first value. You could achieve the same result with something like:

package main

import &quot;fmt&quot;

func main() {
	fmt.Println(request([]string{&quot;foo&quot;, &quot;boo&quot;}))
	fmt.Println(request(nil))
}

func request(wordlist []string) string {
	if len(wordlist) == 0 {
		return &quot;No Data&quot;
	}

	line := wordlist[0]
	// do something...
	return line
}

I suspect that you actually want to process all of the lines but unfortunately your question does not provide sufficient context to assist further.

答案2

得分: 0

你的函数想要查找一个文本。所以在那个循环中:
在找到它后跳出循环,
然后返回该值。
(我稍微简化了一下)

    result := ""
    for _, line := range wordlist {
        if found {
            result = yourAnswer
            break
        }
    }
    return result

}

<details>
<summary>英文:</summary>

Your function wants to lookup a text. 
So in that loop:  
step out of the loop after you found it,  
then return the value.
(I minimised it a bit)
result := &quot;&quot;
for _, line := range wordlist {
    if found {
        result = yourAnswer
        break
    }
}
return result

}

huangapple
  • 本文由 发表于 2021年12月8日 04:05:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/70266295.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定