Golang get decimal separator for current culture - go

Is there a way in Golang to get the current OS decimal separator in windows?
I know that in the Geographic area settings in control panel you can assign your custom decimal separator, so there must be a way to get this value... or no?
I want to use fmt.Printf() and format any float with the OS current decimal symbol.

I want to use fmt.Printf() and format any float with the OS current decimal symbol.
To get the current language OS, you might use a cross platform package such as https://github.com/cloudfoundry-attic/jibber_jabber
To print localized texts you might use the text package available here https://godoc.org/golang.org/x/text
Example
package main
import (
"fmt"
"github.com/cloudfoundry/jibber_jabber"
"golang.org/x/text/language"
"golang.org/x/text/message"
)
func main() {
userLanguage, err := jibber_jabber.DetectLanguage()
if err != nil {
panic(err)
}
fmt.Println("Language:", userLanguage)
tagLanguage := language.Make(userLanguage)
fmt.Println("Language:", tagLanguage)
{
p := message.NewPrinter(language.BritishEnglish)
p.Printf("There are %v flowers in our garden.\n", 1500)
}
{
p := message.NewPrinter(tagLanguage)
p.Printf("There are %v flowers in our garden.\n", 1500)
}
}
As you can see you don t directly use the fmt package anymore, instead you have to create a Printer and use this one to display the texts appropriately.
to get more details about this package usage you can read https://phraseapp.com/blog/posts/internationalization-i18n-go/
Is there a way in Golang to get the current OS decimal separator in windows?
I have not been able to determine how to extract this information from the text package.

Related

In Go 1.18 strings.Title() is deprecated. What to use now? And how?

As suggested here names of people should be capitalized like John William Smith.
I'm writing a small software in Golang which gets last and first name from user's form inputs.
Until Go 1.18 I was using:
lastname = strings.Title(strings.ToLower(strings.TrimSpace(lastname)))
firstname = strings.Title(strings.ToLower(strings.TrimSpace(firstname)))
It works but now Go 1.18 has deprecated strings.Title().
They suggest to use golang.org/x/text/cases instead.
So I think I should change my code in something like this:
caser := cases.Title(language.Und)
lastname = caser.Title(strings.ToLower(strings.TrimSpace(lastname)))
firstname = caser.Title(strings.ToLower(strings.TrimSpace(firstname)))
It works the same as before.
The difference is for Dutch word like ijsland that should be titled as IJsland and not Ijsland.
The question
In the line caser := cases.Title(language.Und) I'm using Und because I don't know what language Tag to use.
Should I use language.English or language.AmericanEnglish or other?
So far it was like strings.Title() was using Und or English?
As mentioned in documentation strings.Title is deprecated and you should use cases.Title instead.
Deprecated: The rule Title uses for word boundaries does not handle
Unicode punctuation properly. Use golang.org/x/text/cases instead.
Here is an example code of how to use it as from two perspectives:
// Straightforward approach
caser := cases.Title(language.BrazilianPortuguese)
titleStr := caser.String(str)
// Transformer interface aware approach
src := []byte(s)
dest := []byte(s) // dest can also be `dest := src`
caser := cases.Title(language.BrazilianPortuguese)
_, _, err := caser.Transform(dest, src, true)
Make sure to take a look on the transform.Transformer.Transform and cases.Caser in order to understand what each parameter and return values mean, as well as the tool's limitations. For example:
A Caser may be stateful and should therefore not be shared between
goroutines.
Regarding what language to use, you should be aware of their difference in the results, besides that, you should be fine with any choice. Here is a copy from 煎鱼's summary on the differences that cleared it for me:
Go Playground: https://go.dev/play/p/xp59r1BkC9L
func main() {
src := []string{
"hello world!",
"i with dot",
"'n ijsberg",
"here comes O'Brian",
}
for _, c := range []cases.Caser{
cases.Lower(language.Und),
cases.Upper(language.Turkish),
cases.Title(language.Dutch),
cases.Title(language.Und, cases.NoLower),
} {
fmt.Println()
for _, s := range src {
fmt.Println(c.String(s))
}
}
}
With the following output
hello world!
i with dot
'n ijsberg
here comes o'brian
HELLO WORLD!
İ WİTH DOT
'N İJSBERG
HERE COMES O'BRİAN
Hello World!
I With Dot
'n IJsberg
Here Comes O'brian
Hello World!
I With Dot
'N Ijsberg
Here Comes O'Brian
So far it was like strings.Title() was using Und or English?
strings.Title() works based on ASCII, where cases.Title() works based on Unicode, there is no way to get the exact same behavior.
Should I use language.English or language.AmericanEnglish or other?
language.English, language.AmericanEnglish and language.Und all seem to have the same Title rules. Using any of them should get you the closest to the original strings.Title() behavior as you are going to get.
The whole point of using this package with Unicode support is that it is objectively more correct. So pick a tag appropriate for your users.
strings.Title(str) was deprecated, should change to cases.Title(language.Und, cases.NoLower).String(str)
package main
import (
"fmt"
"strings"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
func main() {
fmt.Println(strings.Title("abcABC")) // AbcABC
fmt.Println(cases.Title(language.Und, cases.NoLower).String("abcABC")) // AbcABC
}
Playground : https://go.dev/play/p/i0Eqh3QfxTx
Here is a straightforward example of how to capitalize the initial letter of each string value in the variable using the golang.org/x/text package.
package main
import (
"fmt"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
func main() {
sampleStr := "with value lower, all the letters are lowercase. this is good for poetry perhaps"
caser := cases.Title(language.English)
fmt.Println(caser.String(sampleStr))
}
Output : With Value Lower, All The Letters Are Lowercase. This Is Good For Poetry Perhaps
Playground Example: https://go.dev/play/p/_J8nGVuhYC9

Parsefloat give output in scientific format in golang

i am trying to parse this string "7046260" using Parsefloat function in golang , but i am getting output in scientific format 7.04626e+06. i want the output in the format 7046260. how to get this?
package main
import (
"fmt"
"strconv"
)
func main() {
Value := "7046260"
Fval, err := strconv.ParseFloat(Value, 64)
if err == nil {
fmt.Println(Fval)
}
}
ouput :- 7.04626e+06
Parsefloat give output in scientific format in golang
i am trying to parse this string "7046260" using Parsefloat function in golang , but i am getting output in scientific format 7.04626e+06. i want the output in the format 7046260
You're confusing the floating-point value's (default) formatted output with its internal representation.
ParseFloat is working fine.
You just need to specify an output format:
See the fmt package documentation.
Use Printf to specify a format-string.
Use the format %.0f to instruct Go to print the value as-follows:
% marks the start of a placeholder.
. denotes default width (i.e. don't add leading or trailing zeroes).
0 denotes zero radix precision (i.e. don't print any decimal places, even if the value has them)
f denotes the end of the placeholder, and that the placeholder is for a floating-point value.
I have a few other recommendations:
Local variables in Go should use camelCase, not PascalCase. Go does not encourage the use of snake_case.
You should check err != nil after each nil-returning function returns and either fail-fast (if appropriate), pass the error up (and optionally log it), or handle it gracefully.
When working with floating-point numbers, you should be aware of NaN's special status. The IsNaN function is the only way to correctly check for NaN values (because ( aNaNValue1 == math.NaN ) == false).
The same applies in all languages that implement IEEE-754, including Java, JavaScript, C, C#.NET and Go.
Like so:
package main
import (
"fmt"
"strconv"
"math"
"log"
)
func main() {
numberText := "7046260"
numberFloat, err := strconv.ParseFloat(numberText, 64)
if err != nil {
log.Fatal(err)
}
if math.IsNaN(numberFloat) {
log.Fatal("NaN value encountered")
}
fmt.Printf("%.0f",numberFloat)
fmt.Println()
}

Pick the random value from slice and print on cli

How to pick the random value from slice in golang and i need to display it to cli.I have string which i converted to string array by splitting it. Now i want to choose random string from string array and display to user in cli and i need to ask user to input that particular string which is displayed on screen
and compare the user entered input.
string randgen := ‘na gd tg er dd wq ff gen vf ws’
s:= String.split(randgen,””)
s = [“na”, “gd”, ”er”, “tg”, “er”, “dd”, “wq”, “ff”, “gen”, “vf”, “ws”]
There are some issues with your code. You shouldn't define the type when initializing a variable using :=.
Also, it's not recommended to depend on spaces to construct and split your slice, as it's not clear what will happen if for example you have multiple spaces, or a tab between the characters instead.
This is a minimal solution that 'just works'.
package main
import (
"fmt"
"math/rand"
"strings"
"time"
)
func main() {
randgen := `na gd tg er dd wq ff gen vf ws`
s := strings.Split(randgen, " ")
fmt.Println(s)
rand.Seed(time.Now().UnixNano())
randIdx := rand.Intn(len(s))
fmt.Println("Randomly selected slice value : ", s[randIdx])
}
I would suggest reading the rand package documentation for an explanation of what rand.Seed does. Also, take a look at the shuffle function available in rand, as it's suited to your problem, if you want to build a more robust solution.

Making a full screen Terminal application with Go

I'm trying to build a full screen terminal application. I'm using Go as my language of choice. I've figured out how to read from os.Stdin, but I'm unclear on how to clear the terminal window and manipulate the cursor position. I also want to capture the terminal input without it being printed (echoed back).
My questions are:
How can I effectively clear and print to the terminal with column/row coordinates?
How do I stop the terminal from printing keys pressed
My intent:
I want to create a full screen terminal application that renders it's own UI and handles input internally (hot keys/navigation/etc...).
If there are any libraries that cover this sort of use case please feel free to suggest them.
The easiest way to clear the terminal and set position is via ansi escape codes. However, this may not be the ideal way as variation in terminals may come back to bite you.
fmt.Print("\033[2J") //Clear screen
fmt.Printf("\033[%d;%dH", line, col) // Set cursor position
A better alternative would be to use a library like goncurses or termbox-go (credit: second is from Tim Cooper's comment).
With such a library you can do things like this:
import (
gc "code.google.com/p/goncurses"
)
func main() {
s, err := gc.Init()
if err != nil {
panic(err)
}
defer gc.End()
s.Move(5, 2)
s.Println("Hello")
s.GetChar()
}
Code above copied from Rosetta Code
As of December 2019, I would recommend using rivo/tview library.
(goncurses mentioned by #vastlysuperiorman has not been updated since June 2019 and termbox-go is explicitly declared unmaintained).
Here's the "hello world" app, taken from the project's README (reformatted for readability):
package main
import (
"github.com/rivo/tview"
)
func main() {
box := tview.NewBox().
SetBorder(true).
SetTitle("Hello, world!")
if err := tview.NewApplication().SetRoot(box, true).Run(); err != nil {
panic(err)
}
}
tview provides screenshots and example code as well as the standard godoc reference.
To stop the terminal from printing keys pressed you can use the below code:
import (
"fmt"
"syscall"
"golang.org/x/crypto/ssh/terminal"
)
func main(){
fmt.Print("Enter Value: ")
byteInput, _ := terminal.ReadPassword(int(syscall.Stdin))
input:= string(byteInput)
fmt.Println() // it's necessary to add a new line after user's input
fmt.Printf("Your input is '%s'", input)
}

How to evaluate external go source code "dynamically"?

I need to parse a Go source code file, find a specific type (by name) and use it in my program.
I already managed to find the type I need using the go/ast package but I don't know how to "load" it into my program so that I can use it.
Question: What's the best way to extract and use a type from an external source code file and use it on runtime?
I can't think of anything except an ugly method to basically copy the file, modify it by injecting a "main" function with my encoding stuff which sends the result to stdOut, execute the it, collect the encoded data from stdout, delete the modified file.
Use case: Analyse go source code and encode the types in a specific format (e.g. json schema)
Edit:
Here is some code. The question is how to encode type allTypes (zero value) and then print it.
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"encoding/json"
)
var src string = `
package mypack
type allTypes struct{
Brands Brands
Colours Colours
}
type Brands struct{
Sony string
Apple string
}
type Colours struct{
Red string
Green string
}
`
type sometype struct{
Nothing int
}
func main() {
// src is the input for which we want to inspect the AST.
// Create the AST by parsing src.
fset := token.NewFileSet() // positions are relative to fset
f, err := parser.ParseFile(fset, "src.go", src, 0)
if err != nil {
panic(err)
}
// Inspect the AST and find our function
var tp ast.TypeSpec
ast.Inspect(f, func(n ast.Node) bool {
switch x := n.(type) {
case *ast.TypeSpec:
if x.Name.Name == "allTypes"{
tp = *x
}
}
return true
})
fmt.Printf("We found the type: it is %v", tp)
// Encode the zero value of sometype
x := sometype{}
b, _ := json.Marshal(&x)
fmt.Printf("\n Zero value of someType (json) %s", b)
//Next/Question: How to encode the zero value of "allTypes" ???
}
Also on playground
If I understand you are asking for dynamic type loading ala Java's Class.forName(String className). The short answer is Go doesn't support this.
The correct way, as Nick Johnson pointed out, is to parse the tree using ast, and then "generate" the JSON yourself. You will not be able to "load" the type and use JSON.Marshal. It is also worth noting that any type which supports the json.Marshaler interface may generate custom JSON. You also need to ignore, but mark optional "omitempty" behavior. This really prevents you from using the compile it and hack through "stdout" behavior as well.
If you need to extract type information at runtime, you need to use the reflect package. This is the way Go's encoding/json and other similar packages work.
If you want to operate on the types defined in a Go source file, you can use the go.parser package to read and parse a source file into an AST, then traverse the AST for the elements you want to examine.
It seems there is no way to load the type information extracted from the source code(please correct me if I'm wrong). The only solution is to create/generate a package (main), inject it with all the types extracted from the target source code file, build/compile it, execute it and collect the encoded data from stdout.

Resources