Questions about passing arguments

Hello again Golang Bridge! How your day? Hope it’s good!

I spent more than year without Go, and this deprived me of thinking in Go. So yes. I have a few different questions for a few different examples. And looking someone who explain me why/why not.

This will probably be a set of stupid questions in this forum.. Sorry if something is unclear, I tried to avoid chaos.

1. First
I want to read value from user input. For example, let it be a piece of code:

Reading inputn and passing arguments in reading func.

     func readInput() {
    	var lines, columns int
    	fmt.Println("Lines:")
    	fmt.Scan(&lines)
    	fmt.Println("Columns:")
    	fmt.Scan(&columns)

    	mulTab(lines, columns)    // passing values here
    }

    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
    }

I want to pass values from the input to the mulTab func. Is this a good practice to call mulTab func in readInput func? Is there any other (better) way to do this?

2. Second
In the second example I want to list files in directory. Yes I know there’s much better idea like a ioutil.Readdir. But that;s not what my question is about.

  • Is it correct to pass as an argument a whole func like I do in main()?
  • In func readDir() I commented a defer f.Close() because when I close here, in func listDir() there was an error ‘use of closed file’. Can I do os.Open() in one func and close in another?
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. Third

I want create a file. Then I would like to be able to write something to this file in another function. How to pass filename to another func? Suppose the file name is unknown (The file name can be taken from input). os.Create returning os.File and to os.OpenFile() I need to return 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
}

I can’t pass filename from create() to write() because ioutil.WriteFile accepts only string as a filename when create() returns os.File`.

func write() {
	os.OpenFile()
	err := ioutil.WriteFile("file.txt", data, 0644) {

	}
}

Or maybe I just should not break the code into small functions and do such operations in one function? I’m looking for the right way, that’s why I used such examples.

If you want to call a function you have to call it. If you want to call mulTab using arguments gatherd from a different source than STDIN, you should change readInput to return lines and columns and use them to call mulTab.

In fact that’s what you do in your second code snippet: you call readDir and use the result as the argument for listDir.

OK, I will limit my answer to these two points that are related. Please open different topics for the second bullet point in your second question and the third question.

One fuction should perform a single task. As parrallel to lutzhorn’s comments please see my approach below. I could’t understand what mulTab is doing so i wrote directly the same function.

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)
}

For second and third are also connected with the same question. Write a function which returns a pointer, after receiving them you can defer closing.

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()

    //do something with the file
}

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.