Equivalent of Python string.format in Go?
In Python, you can do this:
"File {file} had error {error}".format(file=myfile, error=err)
or this:
"File %(file)s had error %(error)s" % {"file": myfile, "error": err}
In Go, the simplest option is:
fmt.Sprintf("File %s had error %s", myfile, err)
which doesn't let you swap the order of the parameters in the format string, which you need to do for I18N. Go does have the template
package, which would require something like:
package main
import (
"bytes"
"text/template"
"os"
)
func main() {
type Params struct {
File string
Error string
}
var msg bytes.Buffer
params := &Params{
File: "abc",
Error: "def",
}
tmpl, _ := template.New("errmsg").Parse("File {{.File}} has error {{.Error}}")
tmpl.Execute(&msg, params)
msg.WriteTo(os.Stdout)
}
which seems like a long way to go for an error message. Is there a more reasonable option that allows me to give string parameters independent of order?
python string go
add a comment |
In Python, you can do this:
"File {file} had error {error}".format(file=myfile, error=err)
or this:
"File %(file)s had error %(error)s" % {"file": myfile, "error": err}
In Go, the simplest option is:
fmt.Sprintf("File %s had error %s", myfile, err)
which doesn't let you swap the order of the parameters in the format string, which you need to do for I18N. Go does have the template
package, which would require something like:
package main
import (
"bytes"
"text/template"
"os"
)
func main() {
type Params struct {
File string
Error string
}
var msg bytes.Buffer
params := &Params{
File: "abc",
Error: "def",
}
tmpl, _ := template.New("errmsg").Parse("File {{.File}} has error {{.Error}}")
tmpl.Execute(&msg, params)
msg.WriteTo(os.Stdout)
}
which seems like a long way to go for an error message. Is there a more reasonable option that allows me to give string parameters independent of order?
python string go
add a comment |
In Python, you can do this:
"File {file} had error {error}".format(file=myfile, error=err)
or this:
"File %(file)s had error %(error)s" % {"file": myfile, "error": err}
In Go, the simplest option is:
fmt.Sprintf("File %s had error %s", myfile, err)
which doesn't let you swap the order of the parameters in the format string, which you need to do for I18N. Go does have the template
package, which would require something like:
package main
import (
"bytes"
"text/template"
"os"
)
func main() {
type Params struct {
File string
Error string
}
var msg bytes.Buffer
params := &Params{
File: "abc",
Error: "def",
}
tmpl, _ := template.New("errmsg").Parse("File {{.File}} has error {{.Error}}")
tmpl.Execute(&msg, params)
msg.WriteTo(os.Stdout)
}
which seems like a long way to go for an error message. Is there a more reasonable option that allows me to give string parameters independent of order?
python string go
In Python, you can do this:
"File {file} had error {error}".format(file=myfile, error=err)
or this:
"File %(file)s had error %(error)s" % {"file": myfile, "error": err}
In Go, the simplest option is:
fmt.Sprintf("File %s had error %s", myfile, err)
which doesn't let you swap the order of the parameters in the format string, which you need to do for I18N. Go does have the template
package, which would require something like:
package main
import (
"bytes"
"text/template"
"os"
)
func main() {
type Params struct {
File string
Error string
}
var msg bytes.Buffer
params := &Params{
File: "abc",
Error: "def",
}
tmpl, _ := template.New("errmsg").Parse("File {{.File}} has error {{.Error}}")
tmpl.Execute(&msg, params)
msg.WriteTo(os.Stdout)
}
which seems like a long way to go for an error message. Is there a more reasonable option that allows me to give string parameters independent of order?
python string go
python string go
edited Oct 26 '18 at 9:05
icza
166k25330364
166k25330364
asked Nov 25 '16 at 19:10
Scott DeerwesterScott Deerwester
97111027
97111027
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
With strings.Replacer
Using strings.Replacer
, implementing a formatter of your desire is very easy and compact.
func main() {
file, err := "/data/test.txt", "file not found"
log("File {file} had error {error}", "{file}", file, "{error}", err)
}
func log(format string, args ...string) {
r := strings.NewReplacer(args...)
fmt.Println(r.Replace(format))
}
Output (try it on the Go Playground):
File /data/test.txt had error file not found
We can make it more pleasant to use by adding the brackets to the parameter names automatically in the log()
function:
func main() {
file, err := "/data/test.txt", "file not found"
log2("File {file} had error {error}", "file", file, "error", err)
}
func log2(format string, args ...string) {
for i, v := range args {
if i%2 == 0 {
args[i] = "{" + v + "}"
}
}
r := strings.NewReplacer(args...)
fmt.Println(r.Replace(format))
}
Output (try it on the Go Playground):
File /data/test.txt had error file not found
Yes, you could say that this only accepts string
parameter values. This is true. With a little more improvement, this won't be true:
func main() {
file, err := "/data/test.txt", 666
log3("File {file} had error {error}", "file", file, "error", err)
}
func log3(format string, args ...interface{}) {
args2 := make(string, len(args))
for i, v := range args {
if i%2 == 0 {
args2[i] = fmt.Sprintf("{%v}", v)
} else {
args2[i] = fmt.Sprint(v)
}
}
r := strings.NewReplacer(args2...)
fmt.Println(r.Replace(format))
}
Output (try it on the Go Playground):
File /data/test.txt had error 666
A variant of this to accept params as a map[string]interface{}
and return the result as a string
:
type P map[string]interface{}
func main() {
file, err := "/data/test.txt", 666
s := log33("File {file} had error {error}", P{"file": file, "error": err})
fmt.Println(s)
}
func log33(format string, p P) string {
args, i := make(string, len(p)*2), 0
for k, v := range p {
args[i] = "{" + k + "}"
args[i+1] = fmt.Sprint(v)
i += 2
}
return strings.NewReplacer(args...).Replace(format)
}
Try it on the Go Playground.
With text/template
Your template solution or proposal is also way too verbose. It can be written as compact as this (error checks omitted):
type P map[string]interface{}
func main() {
file, err := "/data/test.txt", 666
log4("File {{.file}} has error {{.error}}", P{"file": file, "error": err})
}
func log4(format string, p P) {
t := template.Must(template.New("").Parse(format))
t.Execute(os.Stdout, p)
}
Output (try it on the Go Playground):
File /data/test.txt has error 666
If you want to return the string
(instead of printing it to the standard output), you may do it like this (try it on the Go Playground):
func log5(format string, p P) string {
b := &bytes.Buffer{}
template.Must(template.New("").Parse(format)).Execute(b, p)
return b.String()
}
Using explicit argument indices
This was already mentioned in another answer, but to complete it, know that the same explicit argument index may be used arbitrary number of times and thus resulting in the same parameter substituted in multiple times. Read more about this in this question: Replace all variables in Sprintf with same variable
I suppose that you could also combine the approach in my answer using a map, below, with your approach in log3, putting the args into a map instead of a string array and then formatting it as you do with log4. A lot of the complication in my example was to achieve returning a string. Could you modify log4 to accommodate that?
– Scott Deerwester
Nov 25 '16 at 20:30
@ScottDeerwester Yes, added alog33()
variant taking amap
and returning the result as astring
, also added alog5()
variant returning the result instead of printing it to the standard output.
– icza
Nov 25 '16 at 20:42
@icza: Thanks for an awesome answer. I wonder if, almost a year later, there's a better way of doing this? In the end, I went withstrings.Replacer
, and it seems to work fine.
– elo80ka
Oct 28 '17 at 13:26
@elo80ka Not that I know of. You have the same options as a year before.
– icza
Oct 30 '17 at 9:48
add a comment |
I don't know of any easy way of naming the parameters, but you can easily change the order of the arguments, using explicit argument indexes:
From docs:
In Printf, Sprintf, and Fprintf, the default behavior is for each formatting verb to format successive arguments passed in the call. However, the notation [n] immediately before the verb indicates that the nth one-indexed argument is to be formatted instead. The same notation before a '*' for a width or precision selects the argument index holding the value. After processing a bracketed expression [n], subsequent verbs will use arguments n+1, n+2, etc. unless otherwise directed.
Then you can, ie:
fmt.Printf("File %[2]s had error %[1]s", err, myfile)
add a comment |
The parameter can also be a map, so the following function would work if you don't mind parsing every error format every time you use it:
package main
import (
"bytes"
"text/template"
"fmt"
)
func msg(fmt string, args map[string]interface{}) (str string) {
var msg bytes.Buffer
tmpl, err := template.New("errmsg").Parse(fmt)
if err != nil {
return fmt
}
tmpl.Execute(&msg, args)
return msg.String()
}
func main() {
fmt.Printf(msg("File {{.File}} has error {{.Error}}n", map[string]interface{} {
"File": "abc",
"Error": "def",
}))
}
It's still a little wordier than I would have liked, but it's better than some other options, I suppose. You could turn map[string]interface{}
into a local type and reduce it further to:
type P map[string]interface{}
fmt.Printf(msg("File {{.File}} has error {{.Error}}n", P{
"File": "abc",
"Error": "def",
}))
add a comment |
Alas, there's no built-in function in Go for string interpolation with named parameters (yet). But you are not the only one suffering out there :) Some packages should exist, for example: https://github.com/imkira/go-interpol . Or, if feeling adventurous, you could write such a helper yourself, as the concept is actually quite simple.
Cheers,
Dennis
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f40811117%2fequivalent-of-python-string-format-in-go%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
With strings.Replacer
Using strings.Replacer
, implementing a formatter of your desire is very easy and compact.
func main() {
file, err := "/data/test.txt", "file not found"
log("File {file} had error {error}", "{file}", file, "{error}", err)
}
func log(format string, args ...string) {
r := strings.NewReplacer(args...)
fmt.Println(r.Replace(format))
}
Output (try it on the Go Playground):
File /data/test.txt had error file not found
We can make it more pleasant to use by adding the brackets to the parameter names automatically in the log()
function:
func main() {
file, err := "/data/test.txt", "file not found"
log2("File {file} had error {error}", "file", file, "error", err)
}
func log2(format string, args ...string) {
for i, v := range args {
if i%2 == 0 {
args[i] = "{" + v + "}"
}
}
r := strings.NewReplacer(args...)
fmt.Println(r.Replace(format))
}
Output (try it on the Go Playground):
File /data/test.txt had error file not found
Yes, you could say that this only accepts string
parameter values. This is true. With a little more improvement, this won't be true:
func main() {
file, err := "/data/test.txt", 666
log3("File {file} had error {error}", "file", file, "error", err)
}
func log3(format string, args ...interface{}) {
args2 := make(string, len(args))
for i, v := range args {
if i%2 == 0 {
args2[i] = fmt.Sprintf("{%v}", v)
} else {
args2[i] = fmt.Sprint(v)
}
}
r := strings.NewReplacer(args2...)
fmt.Println(r.Replace(format))
}
Output (try it on the Go Playground):
File /data/test.txt had error 666
A variant of this to accept params as a map[string]interface{}
and return the result as a string
:
type P map[string]interface{}
func main() {
file, err := "/data/test.txt", 666
s := log33("File {file} had error {error}", P{"file": file, "error": err})
fmt.Println(s)
}
func log33(format string, p P) string {
args, i := make(string, len(p)*2), 0
for k, v := range p {
args[i] = "{" + k + "}"
args[i+1] = fmt.Sprint(v)
i += 2
}
return strings.NewReplacer(args...).Replace(format)
}
Try it on the Go Playground.
With text/template
Your template solution or proposal is also way too verbose. It can be written as compact as this (error checks omitted):
type P map[string]interface{}
func main() {
file, err := "/data/test.txt", 666
log4("File {{.file}} has error {{.error}}", P{"file": file, "error": err})
}
func log4(format string, p P) {
t := template.Must(template.New("").Parse(format))
t.Execute(os.Stdout, p)
}
Output (try it on the Go Playground):
File /data/test.txt has error 666
If you want to return the string
(instead of printing it to the standard output), you may do it like this (try it on the Go Playground):
func log5(format string, p P) string {
b := &bytes.Buffer{}
template.Must(template.New("").Parse(format)).Execute(b, p)
return b.String()
}
Using explicit argument indices
This was already mentioned in another answer, but to complete it, know that the same explicit argument index may be used arbitrary number of times and thus resulting in the same parameter substituted in multiple times. Read more about this in this question: Replace all variables in Sprintf with same variable
I suppose that you could also combine the approach in my answer using a map, below, with your approach in log3, putting the args into a map instead of a string array and then formatting it as you do with log4. A lot of the complication in my example was to achieve returning a string. Could you modify log4 to accommodate that?
– Scott Deerwester
Nov 25 '16 at 20:30
@ScottDeerwester Yes, added alog33()
variant taking amap
and returning the result as astring
, also added alog5()
variant returning the result instead of printing it to the standard output.
– icza
Nov 25 '16 at 20:42
@icza: Thanks for an awesome answer. I wonder if, almost a year later, there's a better way of doing this? In the end, I went withstrings.Replacer
, and it seems to work fine.
– elo80ka
Oct 28 '17 at 13:26
@elo80ka Not that I know of. You have the same options as a year before.
– icza
Oct 30 '17 at 9:48
add a comment |
With strings.Replacer
Using strings.Replacer
, implementing a formatter of your desire is very easy and compact.
func main() {
file, err := "/data/test.txt", "file not found"
log("File {file} had error {error}", "{file}", file, "{error}", err)
}
func log(format string, args ...string) {
r := strings.NewReplacer(args...)
fmt.Println(r.Replace(format))
}
Output (try it on the Go Playground):
File /data/test.txt had error file not found
We can make it more pleasant to use by adding the brackets to the parameter names automatically in the log()
function:
func main() {
file, err := "/data/test.txt", "file not found"
log2("File {file} had error {error}", "file", file, "error", err)
}
func log2(format string, args ...string) {
for i, v := range args {
if i%2 == 0 {
args[i] = "{" + v + "}"
}
}
r := strings.NewReplacer(args...)
fmt.Println(r.Replace(format))
}
Output (try it on the Go Playground):
File /data/test.txt had error file not found
Yes, you could say that this only accepts string
parameter values. This is true. With a little more improvement, this won't be true:
func main() {
file, err := "/data/test.txt", 666
log3("File {file} had error {error}", "file", file, "error", err)
}
func log3(format string, args ...interface{}) {
args2 := make(string, len(args))
for i, v := range args {
if i%2 == 0 {
args2[i] = fmt.Sprintf("{%v}", v)
} else {
args2[i] = fmt.Sprint(v)
}
}
r := strings.NewReplacer(args2...)
fmt.Println(r.Replace(format))
}
Output (try it on the Go Playground):
File /data/test.txt had error 666
A variant of this to accept params as a map[string]interface{}
and return the result as a string
:
type P map[string]interface{}
func main() {
file, err := "/data/test.txt", 666
s := log33("File {file} had error {error}", P{"file": file, "error": err})
fmt.Println(s)
}
func log33(format string, p P) string {
args, i := make(string, len(p)*2), 0
for k, v := range p {
args[i] = "{" + k + "}"
args[i+1] = fmt.Sprint(v)
i += 2
}
return strings.NewReplacer(args...).Replace(format)
}
Try it on the Go Playground.
With text/template
Your template solution or proposal is also way too verbose. It can be written as compact as this (error checks omitted):
type P map[string]interface{}
func main() {
file, err := "/data/test.txt", 666
log4("File {{.file}} has error {{.error}}", P{"file": file, "error": err})
}
func log4(format string, p P) {
t := template.Must(template.New("").Parse(format))
t.Execute(os.Stdout, p)
}
Output (try it on the Go Playground):
File /data/test.txt has error 666
If you want to return the string
(instead of printing it to the standard output), you may do it like this (try it on the Go Playground):
func log5(format string, p P) string {
b := &bytes.Buffer{}
template.Must(template.New("").Parse(format)).Execute(b, p)
return b.String()
}
Using explicit argument indices
This was already mentioned in another answer, but to complete it, know that the same explicit argument index may be used arbitrary number of times and thus resulting in the same parameter substituted in multiple times. Read more about this in this question: Replace all variables in Sprintf with same variable
I suppose that you could also combine the approach in my answer using a map, below, with your approach in log3, putting the args into a map instead of a string array and then formatting it as you do with log4. A lot of the complication in my example was to achieve returning a string. Could you modify log4 to accommodate that?
– Scott Deerwester
Nov 25 '16 at 20:30
@ScottDeerwester Yes, added alog33()
variant taking amap
and returning the result as astring
, also added alog5()
variant returning the result instead of printing it to the standard output.
– icza
Nov 25 '16 at 20:42
@icza: Thanks for an awesome answer. I wonder if, almost a year later, there's a better way of doing this? In the end, I went withstrings.Replacer
, and it seems to work fine.
– elo80ka
Oct 28 '17 at 13:26
@elo80ka Not that I know of. You have the same options as a year before.
– icza
Oct 30 '17 at 9:48
add a comment |
With strings.Replacer
Using strings.Replacer
, implementing a formatter of your desire is very easy and compact.
func main() {
file, err := "/data/test.txt", "file not found"
log("File {file} had error {error}", "{file}", file, "{error}", err)
}
func log(format string, args ...string) {
r := strings.NewReplacer(args...)
fmt.Println(r.Replace(format))
}
Output (try it on the Go Playground):
File /data/test.txt had error file not found
We can make it more pleasant to use by adding the brackets to the parameter names automatically in the log()
function:
func main() {
file, err := "/data/test.txt", "file not found"
log2("File {file} had error {error}", "file", file, "error", err)
}
func log2(format string, args ...string) {
for i, v := range args {
if i%2 == 0 {
args[i] = "{" + v + "}"
}
}
r := strings.NewReplacer(args...)
fmt.Println(r.Replace(format))
}
Output (try it on the Go Playground):
File /data/test.txt had error file not found
Yes, you could say that this only accepts string
parameter values. This is true. With a little more improvement, this won't be true:
func main() {
file, err := "/data/test.txt", 666
log3("File {file} had error {error}", "file", file, "error", err)
}
func log3(format string, args ...interface{}) {
args2 := make(string, len(args))
for i, v := range args {
if i%2 == 0 {
args2[i] = fmt.Sprintf("{%v}", v)
} else {
args2[i] = fmt.Sprint(v)
}
}
r := strings.NewReplacer(args2...)
fmt.Println(r.Replace(format))
}
Output (try it on the Go Playground):
File /data/test.txt had error 666
A variant of this to accept params as a map[string]interface{}
and return the result as a string
:
type P map[string]interface{}
func main() {
file, err := "/data/test.txt", 666
s := log33("File {file} had error {error}", P{"file": file, "error": err})
fmt.Println(s)
}
func log33(format string, p P) string {
args, i := make(string, len(p)*2), 0
for k, v := range p {
args[i] = "{" + k + "}"
args[i+1] = fmt.Sprint(v)
i += 2
}
return strings.NewReplacer(args...).Replace(format)
}
Try it on the Go Playground.
With text/template
Your template solution or proposal is also way too verbose. It can be written as compact as this (error checks omitted):
type P map[string]interface{}
func main() {
file, err := "/data/test.txt", 666
log4("File {{.file}} has error {{.error}}", P{"file": file, "error": err})
}
func log4(format string, p P) {
t := template.Must(template.New("").Parse(format))
t.Execute(os.Stdout, p)
}
Output (try it on the Go Playground):
File /data/test.txt has error 666
If you want to return the string
(instead of printing it to the standard output), you may do it like this (try it on the Go Playground):
func log5(format string, p P) string {
b := &bytes.Buffer{}
template.Must(template.New("").Parse(format)).Execute(b, p)
return b.String()
}
Using explicit argument indices
This was already mentioned in another answer, but to complete it, know that the same explicit argument index may be used arbitrary number of times and thus resulting in the same parameter substituted in multiple times. Read more about this in this question: Replace all variables in Sprintf with same variable
With strings.Replacer
Using strings.Replacer
, implementing a formatter of your desire is very easy and compact.
func main() {
file, err := "/data/test.txt", "file not found"
log("File {file} had error {error}", "{file}", file, "{error}", err)
}
func log(format string, args ...string) {
r := strings.NewReplacer(args...)
fmt.Println(r.Replace(format))
}
Output (try it on the Go Playground):
File /data/test.txt had error file not found
We can make it more pleasant to use by adding the brackets to the parameter names automatically in the log()
function:
func main() {
file, err := "/data/test.txt", "file not found"
log2("File {file} had error {error}", "file", file, "error", err)
}
func log2(format string, args ...string) {
for i, v := range args {
if i%2 == 0 {
args[i] = "{" + v + "}"
}
}
r := strings.NewReplacer(args...)
fmt.Println(r.Replace(format))
}
Output (try it on the Go Playground):
File /data/test.txt had error file not found
Yes, you could say that this only accepts string
parameter values. This is true. With a little more improvement, this won't be true:
func main() {
file, err := "/data/test.txt", 666
log3("File {file} had error {error}", "file", file, "error", err)
}
func log3(format string, args ...interface{}) {
args2 := make(string, len(args))
for i, v := range args {
if i%2 == 0 {
args2[i] = fmt.Sprintf("{%v}", v)
} else {
args2[i] = fmt.Sprint(v)
}
}
r := strings.NewReplacer(args2...)
fmt.Println(r.Replace(format))
}
Output (try it on the Go Playground):
File /data/test.txt had error 666
A variant of this to accept params as a map[string]interface{}
and return the result as a string
:
type P map[string]interface{}
func main() {
file, err := "/data/test.txt", 666
s := log33("File {file} had error {error}", P{"file": file, "error": err})
fmt.Println(s)
}
func log33(format string, p P) string {
args, i := make(string, len(p)*2), 0
for k, v := range p {
args[i] = "{" + k + "}"
args[i+1] = fmt.Sprint(v)
i += 2
}
return strings.NewReplacer(args...).Replace(format)
}
Try it on the Go Playground.
With text/template
Your template solution or proposal is also way too verbose. It can be written as compact as this (error checks omitted):
type P map[string]interface{}
func main() {
file, err := "/data/test.txt", 666
log4("File {{.file}} has error {{.error}}", P{"file": file, "error": err})
}
func log4(format string, p P) {
t := template.Must(template.New("").Parse(format))
t.Execute(os.Stdout, p)
}
Output (try it on the Go Playground):
File /data/test.txt has error 666
If you want to return the string
(instead of printing it to the standard output), you may do it like this (try it on the Go Playground):
func log5(format string, p P) string {
b := &bytes.Buffer{}
template.Must(template.New("").Parse(format)).Execute(b, p)
return b.String()
}
Using explicit argument indices
This was already mentioned in another answer, but to complete it, know that the same explicit argument index may be used arbitrary number of times and thus resulting in the same parameter substituted in multiple times. Read more about this in this question: Replace all variables in Sprintf with same variable
edited May 23 '17 at 11:46
Community♦
11
11
answered Nov 25 '16 at 20:01
iczaicza
166k25330364
166k25330364
I suppose that you could also combine the approach in my answer using a map, below, with your approach in log3, putting the args into a map instead of a string array and then formatting it as you do with log4. A lot of the complication in my example was to achieve returning a string. Could you modify log4 to accommodate that?
– Scott Deerwester
Nov 25 '16 at 20:30
@ScottDeerwester Yes, added alog33()
variant taking amap
and returning the result as astring
, also added alog5()
variant returning the result instead of printing it to the standard output.
– icza
Nov 25 '16 at 20:42
@icza: Thanks for an awesome answer. I wonder if, almost a year later, there's a better way of doing this? In the end, I went withstrings.Replacer
, and it seems to work fine.
– elo80ka
Oct 28 '17 at 13:26
@elo80ka Not that I know of. You have the same options as a year before.
– icza
Oct 30 '17 at 9:48
add a comment |
I suppose that you could also combine the approach in my answer using a map, below, with your approach in log3, putting the args into a map instead of a string array and then formatting it as you do with log4. A lot of the complication in my example was to achieve returning a string. Could you modify log4 to accommodate that?
– Scott Deerwester
Nov 25 '16 at 20:30
@ScottDeerwester Yes, added alog33()
variant taking amap
and returning the result as astring
, also added alog5()
variant returning the result instead of printing it to the standard output.
– icza
Nov 25 '16 at 20:42
@icza: Thanks for an awesome answer. I wonder if, almost a year later, there's a better way of doing this? In the end, I went withstrings.Replacer
, and it seems to work fine.
– elo80ka
Oct 28 '17 at 13:26
@elo80ka Not that I know of. You have the same options as a year before.
– icza
Oct 30 '17 at 9:48
I suppose that you could also combine the approach in my answer using a map, below, with your approach in log3, putting the args into a map instead of a string array and then formatting it as you do with log4. A lot of the complication in my example was to achieve returning a string. Could you modify log4 to accommodate that?
– Scott Deerwester
Nov 25 '16 at 20:30
I suppose that you could also combine the approach in my answer using a map, below, with your approach in log3, putting the args into a map instead of a string array and then formatting it as you do with log4. A lot of the complication in my example was to achieve returning a string. Could you modify log4 to accommodate that?
– Scott Deerwester
Nov 25 '16 at 20:30
@ScottDeerwester Yes, added a
log33()
variant taking a map
and returning the result as a string
, also added a log5()
variant returning the result instead of printing it to the standard output.– icza
Nov 25 '16 at 20:42
@ScottDeerwester Yes, added a
log33()
variant taking a map
and returning the result as a string
, also added a log5()
variant returning the result instead of printing it to the standard output.– icza
Nov 25 '16 at 20:42
@icza: Thanks for an awesome answer. I wonder if, almost a year later, there's a better way of doing this? In the end, I went with
strings.Replacer
, and it seems to work fine.– elo80ka
Oct 28 '17 at 13:26
@icza: Thanks for an awesome answer. I wonder if, almost a year later, there's a better way of doing this? In the end, I went with
strings.Replacer
, and it seems to work fine.– elo80ka
Oct 28 '17 at 13:26
@elo80ka Not that I know of. You have the same options as a year before.
– icza
Oct 30 '17 at 9:48
@elo80ka Not that I know of. You have the same options as a year before.
– icza
Oct 30 '17 at 9:48
add a comment |
I don't know of any easy way of naming the parameters, but you can easily change the order of the arguments, using explicit argument indexes:
From docs:
In Printf, Sprintf, and Fprintf, the default behavior is for each formatting verb to format successive arguments passed in the call. However, the notation [n] immediately before the verb indicates that the nth one-indexed argument is to be formatted instead. The same notation before a '*' for a width or precision selects the argument index holding the value. After processing a bracketed expression [n], subsequent verbs will use arguments n+1, n+2, etc. unless otherwise directed.
Then you can, ie:
fmt.Printf("File %[2]s had error %[1]s", err, myfile)
add a comment |
I don't know of any easy way of naming the parameters, but you can easily change the order of the arguments, using explicit argument indexes:
From docs:
In Printf, Sprintf, and Fprintf, the default behavior is for each formatting verb to format successive arguments passed in the call. However, the notation [n] immediately before the verb indicates that the nth one-indexed argument is to be formatted instead. The same notation before a '*' for a width or precision selects the argument index holding the value. After processing a bracketed expression [n], subsequent verbs will use arguments n+1, n+2, etc. unless otherwise directed.
Then you can, ie:
fmt.Printf("File %[2]s had error %[1]s", err, myfile)
add a comment |
I don't know of any easy way of naming the parameters, but you can easily change the order of the arguments, using explicit argument indexes:
From docs:
In Printf, Sprintf, and Fprintf, the default behavior is for each formatting verb to format successive arguments passed in the call. However, the notation [n] immediately before the verb indicates that the nth one-indexed argument is to be formatted instead. The same notation before a '*' for a width or precision selects the argument index holding the value. After processing a bracketed expression [n], subsequent verbs will use arguments n+1, n+2, etc. unless otherwise directed.
Then you can, ie:
fmt.Printf("File %[2]s had error %[1]s", err, myfile)
I don't know of any easy way of naming the parameters, but you can easily change the order of the arguments, using explicit argument indexes:
From docs:
In Printf, Sprintf, and Fprintf, the default behavior is for each formatting verb to format successive arguments passed in the call. However, the notation [n] immediately before the verb indicates that the nth one-indexed argument is to be formatted instead. The same notation before a '*' for a width or precision selects the argument index holding the value. After processing a bracketed expression [n], subsequent verbs will use arguments n+1, n+2, etc. unless otherwise directed.
Then you can, ie:
fmt.Printf("File %[2]s had error %[1]s", err, myfile)
answered Nov 25 '16 at 19:32
hlscalonhlscalon
5,44232338
5,44232338
add a comment |
add a comment |
The parameter can also be a map, so the following function would work if you don't mind parsing every error format every time you use it:
package main
import (
"bytes"
"text/template"
"fmt"
)
func msg(fmt string, args map[string]interface{}) (str string) {
var msg bytes.Buffer
tmpl, err := template.New("errmsg").Parse(fmt)
if err != nil {
return fmt
}
tmpl.Execute(&msg, args)
return msg.String()
}
func main() {
fmt.Printf(msg("File {{.File}} has error {{.Error}}n", map[string]interface{} {
"File": "abc",
"Error": "def",
}))
}
It's still a little wordier than I would have liked, but it's better than some other options, I suppose. You could turn map[string]interface{}
into a local type and reduce it further to:
type P map[string]interface{}
fmt.Printf(msg("File {{.File}} has error {{.Error}}n", P{
"File": "abc",
"Error": "def",
}))
add a comment |
The parameter can also be a map, so the following function would work if you don't mind parsing every error format every time you use it:
package main
import (
"bytes"
"text/template"
"fmt"
)
func msg(fmt string, args map[string]interface{}) (str string) {
var msg bytes.Buffer
tmpl, err := template.New("errmsg").Parse(fmt)
if err != nil {
return fmt
}
tmpl.Execute(&msg, args)
return msg.String()
}
func main() {
fmt.Printf(msg("File {{.File}} has error {{.Error}}n", map[string]interface{} {
"File": "abc",
"Error": "def",
}))
}
It's still a little wordier than I would have liked, but it's better than some other options, I suppose. You could turn map[string]interface{}
into a local type and reduce it further to:
type P map[string]interface{}
fmt.Printf(msg("File {{.File}} has error {{.Error}}n", P{
"File": "abc",
"Error": "def",
}))
add a comment |
The parameter can also be a map, so the following function would work if you don't mind parsing every error format every time you use it:
package main
import (
"bytes"
"text/template"
"fmt"
)
func msg(fmt string, args map[string]interface{}) (str string) {
var msg bytes.Buffer
tmpl, err := template.New("errmsg").Parse(fmt)
if err != nil {
return fmt
}
tmpl.Execute(&msg, args)
return msg.String()
}
func main() {
fmt.Printf(msg("File {{.File}} has error {{.Error}}n", map[string]interface{} {
"File": "abc",
"Error": "def",
}))
}
It's still a little wordier than I would have liked, but it's better than some other options, I suppose. You could turn map[string]interface{}
into a local type and reduce it further to:
type P map[string]interface{}
fmt.Printf(msg("File {{.File}} has error {{.Error}}n", P{
"File": "abc",
"Error": "def",
}))
The parameter can also be a map, so the following function would work if you don't mind parsing every error format every time you use it:
package main
import (
"bytes"
"text/template"
"fmt"
)
func msg(fmt string, args map[string]interface{}) (str string) {
var msg bytes.Buffer
tmpl, err := template.New("errmsg").Parse(fmt)
if err != nil {
return fmt
}
tmpl.Execute(&msg, args)
return msg.String()
}
func main() {
fmt.Printf(msg("File {{.File}} has error {{.Error}}n", map[string]interface{} {
"File": "abc",
"Error": "def",
}))
}
It's still a little wordier than I would have liked, but it's better than some other options, I suppose. You could turn map[string]interface{}
into a local type and reduce it further to:
type P map[string]interface{}
fmt.Printf(msg("File {{.File}} has error {{.Error}}n", P{
"File": "abc",
"Error": "def",
}))
answered Nov 25 '16 at 19:44
Scott DeerwesterScott Deerwester
97111027
97111027
add a comment |
add a comment |
Alas, there's no built-in function in Go for string interpolation with named parameters (yet). But you are not the only one suffering out there :) Some packages should exist, for example: https://github.com/imkira/go-interpol . Or, if feeling adventurous, you could write such a helper yourself, as the concept is actually quite simple.
Cheers,
Dennis
add a comment |
Alas, there's no built-in function in Go for string interpolation with named parameters (yet). But you are not the only one suffering out there :) Some packages should exist, for example: https://github.com/imkira/go-interpol . Or, if feeling adventurous, you could write such a helper yourself, as the concept is actually quite simple.
Cheers,
Dennis
add a comment |
Alas, there's no built-in function in Go for string interpolation with named parameters (yet). But you are not the only one suffering out there :) Some packages should exist, for example: https://github.com/imkira/go-interpol . Or, if feeling adventurous, you could write such a helper yourself, as the concept is actually quite simple.
Cheers,
Dennis
Alas, there's no built-in function in Go for string interpolation with named parameters (yet). But you are not the only one suffering out there :) Some packages should exist, for example: https://github.com/imkira/go-interpol . Or, if feeling adventurous, you could write such a helper yourself, as the concept is actually quite simple.
Cheers,
Dennis
answered Nov 25 '16 at 20:05
oharlemoharlem
790411
790411
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f40811117%2fequivalent-of-python-string-format-in-go%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown