Open earthboundkid opened 2 years ago
How about https://go.dev/doc/faq#x_in_std? Suggesting better fmt scanning APIs is one thing, but if these APIs are primarly for new Go users, perhaps they should be in a Go module that's aimed and promoted to them.
At the same time, I would be conflicted with APIs targetting new users only. If I was learning a language, I would want to learn the "normal" or "proper" way to accomplish a task, not an oversimplified way that I should probably un-learn later.
I think it's a fair question whether Go wants to target new users or just say that's out of scope. However, if the decision is made that targeting new users is in scope, then I don't think it makes any sense to use an external module. You can already find tons of simple input packages online. The forums are full of people who haven't found those modules because they are looking in the standard library for the equivalent of Python's input()
and then they get burned using fmt.Scanln
instead of what they really want.
I don't think it would be fair to say Go doesn't target new users. It has grown in users at a very fast pace for ten years now :)
It is true that new users will tend to look at the standard library first, but ultimately they will follow the advice of the documentation they are reading. There are plenty of "blessed" modules outside of the standard library, such as x/crypto
and x/net
, and they don't need to be in the standard library either. If there was a module like x/guardrails
or somesuch, I'm sure that pages like tour.golang.org could point to it or show examples with it.
The question of why should this be in the standard library seems really straightforward to me. A simpleinput package really only has value in the standard library. The point is to make learning Go easier, and as soon as modules are involved, it's not easier.
If I was learning a language, I would want to learn the "normal" or "proper" way to accomplish a task, not an oversimplified way that I should probably un-learn later.
In Python, practically all learning material uses print()
and input()
, neither of which did I ever use in my years of programming Python professionally. It's normal to have an inefficient "easy mode" for beginners. Learning styles vary and some people want to learn the "real" way to do things earlier and some people prefer to just get things working and fill in the details later. Neither is better than the other, but I think the latter style is more common.
If we are going to do this, I think we should be more idiomatic and have Read
and friends return (string, error)
.
After reading this proposal I tried to think about some typical "getting started"-type programs that I might write when learning a new language. It's harder for me to relate to "learning to program" because it's been some time, but I also tried to remember some early programs I wrote.
Here's what came to my mind:
Number guessing game: generate random number, prompt for guesses, and print "guess higher", "guess lower", or "correct!" depending on the relationship between the guess and the goal number.
I distinctly remember writing a program like this in my early experiments with programming, based on an example in the Commodore 64 User Guide. This sort of prompt-and-response program seems well-suited to the API described here, if combined with the writing functions in fmt
.
Advent of Code challenges: I have anecdotal evidence that some participants in Advent of Code intentionally choose a language they don't already know and use these challenges as a vehicle for learning.
Advent of Code challenges commonly involve loading in some data in a simple delimited text format, doing some computation based on that data, and printing a result. ReadLines
from this proposal in particular seems like it would be useful in many of the Advent of Code challenges.
I don't really have a strong opinion about whether it's important to make these easy to achieve, but similar features do seem to help learners of Python as stated above, and Python is typically presented as an example of a good language for beginners. My examples above also lead me to think that the simpleinput
API proposed here would be useful for the sorts of problems I can imagine beginners wanting to use to experiment.
I share Ian's sense that it would be better to make these functions follow typical Go error handling patterns, because that seems like an important part of Go's design that I'd want to learn quickly as a beginner, rather than deferring until later. I think a Read (string, error)
does still address the stated problem with fmt.Scanf
where beginners don't think to check the error, because they'll want to access the string result and therefore won't be able to avoid learning how to handle multiple return values, which will hopefully then encourage learning what to do with that error
result. The pattern they'd learn doing that will then set them up for working with almost every fallible API in Go.
Problem:
Every few months, someone will post on Reddit that they're trying to make an intro-to-CS-style input prompt and they're confused why their code using
fmt.Scan*
doesn't work (inevitably because the input has a space and they're ignoring errors). I think that just for the use case of education, there should be something that does the thing that they want.Here are some typical posts
* https://www.reddit.com/r/golang/comments/alvdhl/force_golang_to_scan_a_number_instead_of_a_single/ * https://www.reddit.com/r/golang/comments/atlehx/flushing_standard_input_before_scanf/ * https://www.reddit.com/r/golang/comments/2h5qnw/using_numerical_values_from_slices/ * https://www.reddit.com/r/golang/comments/wv1i2z/can_someone_tell_me_what_im_doing_wrong_im_trying/ * https://www.reddit.com/r/golang/comments/hkz1im/what_is_the_most_idiomatic_way_of_getting_input/ * https://www.reddit.com/r/golang/comments/8umvpt/unclear_on_scan/ * https://www.reddit.com/r/golang/comments/4hktbe/read_user_input_until_he_press_ctrlc/ * https://www.reddit.com/r/golang/comments/tq3wpc/scanln_and_scanf_jump_after_entering_string_value/ * https://www.reddit.com/r/golang/comments/qja60y/issues_with_fmtscanf_reading/ * https://www.reddit.com/r/golang/comments/kee82p/i_am_bit_confused_about_golangs_scanf/ * https://www.reddit.com/r/golang/comments/bkqos6/differences_between_scan_functions/ * https://www.reddit.com/r/golang/comments/whfi8p/question_about_fmtscan/ * https://www.reddit.com/r/golang/comments/p2tnio/in_golang_is_there_is_any_way_to_take_input/ * https://www.reddit.com/r/golang/comments/s85xxl/having_trouble_with_scanning_input_new_to_language/ You can find more by searching site:https://reddit.com/r/golang fmt.scan.New programmers aren't a huge source of new Go users. On the other hand, even if most Go programmers come from other languages, it is convenient when learning the language to be able to write simple intro-to-CS-style question/response programs to get a feel for the language. There ought to be something very simple that novice can find without knowing anything about Go or IO. Obviously, novices could and probably should be using bufio.Scanner already, but they aren't finding it today. Instead they look in fmt (because they are already using fmt.Println) and find the Scan family of functions. Then they are frustrated when it does not work the way they expect.
Proposed solutions
Proposed solution one is simple: mark the Scan functions as deprecated to hide them from the documentation. Even Rob Pike regrets adding the Scan functions.
Proposed solution two is to add a new package just for education purposes.
Obviously, none of this is strictly necessary, but it would help Go learners, particularly those new to programming.
Cf. #54620
Edit: Proposed API is now: