hello: create new standalone module example We want to revive golang.org/x/example as a test case for an experiment with a 'gonew' command. This CL changes the hello world program to be standalone and demonstrate a bit more about flag parsing and command-line logging. Change-Id: Iee481344c801f046813806a537d59e3242f9152a Reviewed-on: https://go-review.googlesource.com/c/example/+/513996 Reviewed-by: Cameron Balahan <cbalahan@google.com> Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Auto-Submit: Russ Cox <rsc@golang.org>
diff --git a/README.md b/README.md index 2dad874..253a18f 100644 --- a/README.md +++ b/README.md
@@ -13,21 +13,25 @@ ``` https://go.googlesource.com/example is the canonical Git repository. It is mirrored at https://github.com/golang/example. -## [hello](hello/) and [stringutil](stringutil/) + +## [hello](hello/) and [hello/reverse](hello/reverse/) ``` $ cd hello $ go build +$ ./hello -help ``` -A trivial "Hello, world" program that uses a stringutil package. +A trivial "Hello, world" program that uses a library package. -Command [hello](hello/) covers: +The [hello](hello/) command covers: * The basic form of an executable command * Importing packages (from the standard library and the local repository) * Printing strings ([fmt](//golang.org/pkg/fmt/)) +* Command-line flags ([flag](//golang.org/pkg/flag/)) +* Logging ([log](//golang.org/pkg/log/)) -Library [stringutil](stringutil/) covers: +The [reverse](hello/reverse/) reverse covers: * The basic form of a library * Conversion between string and []rune @@ -37,7 +41,7 @@ ``` $ cd outyet -$ go build +$ go run . ``` A web server that answers the question: "Is Go 1.x out yet?"
diff --git a/hello/go.mod b/hello/go.mod new file mode 100644 index 0000000..eb0dea6 --- /dev/null +++ b/hello/go.mod
@@ -0,0 +1,4 @@ +module golang.org/x/example/hello + +go 1.19 +
diff --git a/hello/hello.go b/hello/hello.go index 38802d2..ce2a423 100644 --- a/hello/hello.go +++ b/hello/hello.go
@@ -2,14 +2,71 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// Hello is a hello, world program, demonstrating +// how to write a simple command-line program. +// +// Usage: +// +// hello [options] [name] +// +// The options are: +// +// -g greeting +// Greet with the given greeting, instead of "Hello". +// +// -r +// Greet in reverse. +// +// By default, hello greets the world. +// If a name is specified, hello greets that name instead. package main import ( + "flag" "fmt" + "log" + "os" - "golang.org/x/example/stringutil" + "golang.org/x/example/hello/reverse" +) + +func usage() { + fmt.Fprintf(os.Stderr, "usage: hello [options] [name]\n") + flag.PrintDefaults() + os.Exit(2) +} + +var ( + greeting = flag.String("g", "Hello", "Greet with `greeting`") + reverseFlag = flag.Bool("r", false, "Greet in reverse") ) func main() { - fmt.Println(stringutil.Reverse("!selpmaxe oG ,olleH")) + // Configure logging for a command-line program. + log.SetFlags(0) + log.SetPrefix("hello: ") + + // Parse flags. + flag.Usage = usage + flag.Parse() + + // Parse and validate arguments. + name := "world" + args := flag.Args() + if len(args) >= 2 { + usage() + } + if len(args) >= 1 { + name = args[0] + } + if name == "" { // hello '' is an error + log.Fatalf("invalid name %q", name) + } + + // Run actual logic. + if *reverseFlag { + fmt.Printf("%s, %s!\n", reverse.String(*greeting), reverse.String(name)) + return + } + fmt.Printf("%s, %s!\n", *greeting, name) }
diff --git a/hello/reverse/reverse.go b/hello/reverse/reverse.go new file mode 100644 index 0000000..b6fe74a --- /dev/null +++ b/hello/reverse/reverse.go
@@ -0,0 +1,15 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package reverse can reverse things, particularly strings. +package reverse + +// String returns its argument string reversed rune-wise left to right. +func String(s string) string { + r := []rune(s) + for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 { + r[i], r[j] = r[j], r[i] + } + return string(r) +}
diff --git a/stringutil/reverse_test.go b/hello/reverse/reverse_test.go similarity index 71% rename from stringutil/reverse_test.go rename to hello/reverse/reverse_test.go index 9dbe42f..d130117 100644 --- a/stringutil/reverse_test.go +++ b/hello/reverse/reverse_test.go
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package stringutil +package reverse import "testing" -func TestReverse(t *testing.T) { +func TestString(t *testing.T) { for _, c := range []struct { in, want string }{ @@ -14,9 +14,9 @@ {"Hello, 世界", "界世 ,olleH"}, {"", ""}, } { - got := Reverse(c.in) + got := String(c.in) if got != c.want { - t.Errorf("Reverse(%q) == %q, want %q", c.in, got, c.want) + t.Errorf("String(%q) == %q, want %q", c.in, got, c.want) } } }
diff --git a/stringutil/reverse.go b/stringutil/reverse.go deleted file mode 100644 index c7b2463..0000000 --- a/stringutil/reverse.go +++ /dev/null
@@ -1,15 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package stringutil contains utility functions for working with strings. -package stringutil - -// Reverse returns its argument string reversed rune-wise left to right. -func Reverse(s string) string { - r := []rune(s) - for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 { - r[i], r[j] = r[j], r[i] - } - return string(r) -}