Golang中参数传递的相关问题探讨
Golang中参数传递的相关问题探讨 再次问候 Golang Bridge!今天过得怎么样?希望一切顺利!
我已经一年多没有接触 Go 语言了,这让我失去了用 Go 思维思考的能力。所以,是的。我有几个不同的问题,针对几个不同的例子。希望能有人向我解释为什么可以或为什么不可以。
这可能会成为论坛里一系列愚蠢的问题。 如果有什么地方表述不清,请见谅,我已经尽力避免混乱。
1. 第一个问题 我想从用户输入中读取值。例如,下面这段代码:
读取输入并在读取函数中传递参数。
func readInput() {
var lines, columns int
fmt.Println("Lines:")
fmt.Scan(&lines)
fmt.Println("Columns:")
fmt.Scan(&columns)
mulTab(lines, columns) // 在这里传递值
}
func mulTab(lin, col int) int {
var result int
for lines = 1; lines <= lin; lines++ {
for columns = 1; columns <= col; columns++ {
result = columns * lines
fmt.Println(columns, "x", lines, "=", result)
}
}
return result
}
我想将输入的值传递给 mulTab 函数。在 readInput 函数中调用 mulTab 函数,这是好的做法吗?是否有其他(更好的)方法来实现这个?
2. 第二个问题
在第二个例子中,我想列出目录中的文件。是的,我知道有更好的方法,比如 ioutil.Readdir。但这不是我的问题所在。
- 像我这样在
main()中传递整个函数作为参数是否正确? - 在
func readDir()中,我注释掉了defer f.Close(),因为如果我在这里关闭,在func listDir()中会出现 ‘use of closed file’ 错误。我可以在一个函数中进行os.Open()操作,而在另一个函数中关闭它吗?
func readDir() *os.File {
f, err := os.Open(".")
if err != nil {
log.Fatal("Cannot read directory")
}
// defer f.Close()
return f
}
func listDir(s *os.File) []string {
list, err := s.Readdirnames(0)
if err != nil {
log.Fatalln(err)
}
for _, name := range list {
fmt.Println(name)
}
defer s.Close()
return list
}
func main() {
listDir(readDir())
}
3. 第三个问题
我想创建一个文件。然后我希望能够在另一个函数中向这个文件写入内容。如何将文件名传递给另一个函数?假设文件名是未知的(文件名可以从输入中获取)。os.Create 返回 os.File,而 os.OpenFile() 需要我返回 string。
func create() os.File {
f, err := os.Create(filename_from_input)
if err != nil {
log.Fatal("Can't create file:", err)
}
defer f.Close()
return *f
}
我无法将文件名从 create() 传递给 write(),因为 ioutil.WriteFile 只接受 string 类型的文件名,而 create() 返回的是 os.File。
func write() {
os.OpenFile()
err := ioutil.WriteFile("file.txt", data, 0644) {
}
}
或者也许我根本不应该把代码拆分成小函数,而应该在一个函数中完成这些操作?我正在寻找正确的方法,这就是我使用这些例子的原因。
更多关于Golang中参数传递的相关问题探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html
第二点和第三点也与同一个问题相关。编写一个返回指针的函数,在接收后可以延迟关闭。
package main
import (
"log"
"os"
)
func create() *os.File {
f, err := os.Create("filename")
if err != nil {
log.Fatal("Can't create file:", err)
}
return f
}
func main() {
file := create()
defer file.Close()
//对文件进行一些操作
}
更多关于Golang中参数传递的相关问题探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我想将输入的值传递给
mulTab函数。在readInput函数中调用mulTab函数,这是一种好的做法吗?
如果你想调用一个函数,就必须调用它。如果你想使用从标准输入以外的来源收集的参数来调用 mulTab,你应该修改 readInput 函数,使其返回 lines 和 columns,然后用它们来调用 mulTab。
实际上,你在第二个代码片段中就是这么做的:你调用了 readDir 并使用其结果作为 listDir 的参数。
好的,我将我的回答限制在与这两点相关的内容上。关于你第二个问题中的第二点和第三个问题,请另开新帖讨论。
一个函数应该只执行单一任务。与lutzhorn的评论类似,请参考我下面的方法。我不理解mulTab在做什么,所以我直接写了相同的函数。
package main
import "fmt"
type UserInput struct {
Lines int
Columns int
}
func readUserInput() *UserInput {
userInput := UserInput{}
fmt.Println("Lines:")
fmt.Scan(&userInput.Lines)
fmt.Println("Columns:")
fmt.Scan(&userInput.Columns)
return &userInput
}
func mulTab(lin, col int) {
var result int
for lines := 1; lines <= lin; lines++ {
for columns := 1; columns <= col; columns++ {
result = columns * lines
fmt.Println(columns, "x", lines, "=", result)
}
}
}
func main() {
userInput := readUserInput()
mulTab(userInput.Lines, userInput.Columns)
}
回答
1. 第一个问题
你的代码基本正确,但有几个小问题需要修正:
func readInput() {
var lines, columns int
fmt.Print("Lines: ")
fmt.Scan(&lines)
fmt.Print("Columns: ")
fmt.Scan(&columns)
mulTab(lines, columns) // 正确传递值
}
func mulTab(lin, col int) int {
var result int
for lines := 1; lines <= lin; lines++ { // 需要声明lines变量
for columns := 1; columns <= col; columns++ { // 需要声明columns变量
result = columns * lines
fmt.Println(columns, "x", lines, "=", result)
}
}
return result
}
在 mulTab 函数中传递参数是标准做法。更好的做法可能是让 readInput 返回读取的值,由调用者决定如何处理:
func readInput() (int, int) {
var lines, columns int
fmt.Print("Lines: ")
fmt.Scan(&lines)
fmt.Print("Columns: ")
fmt.Scan(&columns)
return lines, columns
}
func main() {
lines, columns := readInput()
mulTab(lines, columns)
}
2. 第二个问题
在 main() 中传递函数返回值作为参数是常见的做法。关于文件关闭的问题:
func readDir() (*os.File, error) {
f, err := os.Open(".")
if err != nil {
return nil, err
}
return f, nil
}
func listDir(s *os.File) ([]string, error) {
defer s.Close() // 在这里关闭更合适
list, err := s.Readdirnames(0)
if err != nil {
return nil, err
}
for _, name := range list {
fmt.Println(name)
}
return list, nil
}
func main() {
f, err := readDir()
if err != nil {
log.Fatal(err)
}
list, err := listDir(f)
if err != nil {
log.Fatal(err)
}
_ = list // 使用返回的列表
}
可以在一个函数中打开文件,在另一个函数中关闭。关键是确保文件在使用完毕后被关闭。
3. 第三个问题
有几种方法可以处理这个问题:
方法1:返回文件名
func create(filename string) (string, error) {
f, err := os.Create(filename)
if err != nil {
return "", err
}
f.Close() // 立即关闭,只创建文件
return filename, nil
}
func write(filename string, data []byte) error {
return ioutil.WriteFile(filename, data, 0644)
}
func main() {
filename := "test.txt"
// 创建文件
_, err := create(filename)
if err != nil {
log.Fatal(err)
}
// 写入内容
data := []byte("Hello, World!")
err = write(filename, data)
if err != nil {
log.Fatal(err)
}
}
方法2:返回文件句柄
func create(filename string) (*os.File, error) {
return os.Create(filename)
}
func write(f *os.File, data []byte) error {
defer f.Close()
_, err := f.Write(data)
return err
}
func main() {
filename := "test.txt"
// 创建并获取文件句柄
f, err := create(filename)
if err != nil {
log.Fatal(err)
}
// 使用文件句柄写入
data := []byte("Hello, World!")
err = write(f, data)
if err != nil {
log.Fatal(err)
}
}
方法3:使用os.OpenFile
func writeToFile(filename string, data []byte) error {
f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
return err
}
defer f.Close()
_, err = f.Write(data)
return err
}
func main() {
filename := "test.txt"
data := []byte("Hello, World!")
err := writeToFile(filename, data)
if err != nil {
log.Fatal(err)
}
}
将代码拆分成小函数是好的实践,可以提高代码的可读性和可维护性。关键是要清晰地定义每个函数的职责和参数传递方式。

