Overriding printf method - go

I want to create a function that will work exactly like fmt.Printf but also left pad the string with current timestamp. Ideally I would like to override printf and println to do this job, but the first solution is also ok.
This is what I've done:
func output(message string, a ...interface{}) {
fmt.Printf(getCurrentTime() + " " + message, a)
}
func getCurrentTime() string {
t := time.Now()
return t.Format("[2006-01-02 15:04:05]")
}
But it outputs strange results when I pass variables.
How should I do this?

If you want to pass variadic elements from a function to another, you have to expand them. From your example, a is an []interface, so you are passing only two arguments to the actual fmt.Printf: the message and an array.
You have to correct the call:
fmt.Printf(getCurrentTime() + " " + message, a...)
A little example to show what happens:
func exec(args ...interface{}) {
fmt.Println(args)
}
func insert(args ...interface{}) {
exec(args) // Prints [[5 42]]
exec(args...) // Prints [5 42]
}
func main() {
insert(5, "42")
}

Related

Rewriting a fprint function in golang

I've found a package for printing colours in golang. However, it has no simple way of printing no colour. And as my code was becoming messier due being filled with print statements I wanted to rewrite it. However, I have no clue how to create fstrings in a function.
How it looks in my code:
color.HEX("#B0DFE5").Print("[" + time.Now().Format("15:04:05") +"] ")
color.HEX("#FFFFFF").Printf("Changed %s to %s\n", name, new_name)
What I've created for normal prints:
func cprintInfo(message string) {
color.HEX("#B0DFE5").Print("[!] ")
color.HEX("#FFFFFF").Printf(message + "\n")
}
What I'm looking to create:
cfprintInfo("Hello %s", world)
// Hello world
Printf() expects a format string and (optional) arguments:
func (c RGBColor) Printf(format string, a ...interface{})
So mimic that:
func cfprintInfo(format string, args ...interface{}) {
color.HEX("#B0DFE5").Print("[!] ")
color.HEX("#FFFFFF").Printf(format, args...)
}

How to spread arguments as parameters

I have the following Golang code:
rows, err := common.GetAll(c, req, params, timer)
return common.GenericRowMarshal(200, rows, err)
I want to figure out if it's possible to do:
return common.GenericRowMarshal(200, common.GetAll(c, req, params, timer)...)
but this doesn't compile :(
It says "not enough arguments to call..."
Anyone know if this is possible somehow?
No, each time a statement executes, the function value and parameters to the call are evaluated as usual, see doc:
As a special case, if the return values of a function or method g are equal in number and individually assignable to the parameters of another function or method f, then the call f(g(parameters_of_g)) will invoke f after binding the return values of g to the parameters of f in order. The call of f must contain no parameters other than the call of g, and g must have at least one return value. If f has a final ... parameter, it is assigned the return values of g that remain after assignment of regular parameters.
func Split(s string, pos int) (string, string) {
return s[0:pos], s[pos:]
}
func Join(s, t string) string {
return s + t
}
if Join(Split(value, len(value)/2)) != value {
log.Panic("test fails")
}
If f has a final ... parameter, it is assigned the return values of g that remain after assignment of regular parameters.
For example, the following code works:
package main
import "fmt"
func main() {
f(200, g())
}
func f(i int, slice ...interface{}) {
fmt.Println(i, slice) // 200 [[1 <nil>]]
}
func g() []interface{} {
return []interface{}{1, nil}
}
I've tried this too, thinking it might work. Currently (Go 1.13) you can only do this if the inner func returns exactly the parameters that the outer function expects.

Allowing for a variable number of return values in method declaration

I have a function that solves the problem of Go not allowing for the setting of default values in method declarations. I want to make it just a little bit better by allowing for a variable number of return variables. I understand that I can allow for an array of interfaces as a return type and then create an interface array with all the variables to return, like this:
func SetParams(params []interface{}, args ...interface{}) (...[]interface{}) {
var values []interface{}
for i := range params {
var value interface{}
paramType := reflect.TypeOf(params[i])
if len(args) < (i + 1) {
value = params[i]
} else {
argType := reflect.TypeOf(args[i])
if paramType != argType {
value = params[i]
}
value = args[i]
}
values = append(values, value)
}
return values
}
This is an example of a method you want to define default values for. You build it as a variadic function (allowing a variable number of parameters) and then define the default values of the specific params you are looking for inside the function instead of in the declaration line.
func DoSomething(args ...interface{}) {
//setup default values
str := "default string 1"
num := 1
str2 := "default string 2"
//this is fine
values := SetParams([]interface{str, num, str2}, args)
str = values[0].(string)
num = values[1].(int)
str = values[2].(string)
//I'd rather support this
str, num, str2 = SetParams(params, args)
}
I understand that
[]interface{str, num, str2}
in the above example is not syntactically correct. I did it that way to simplify my post. But, it represents another function that builds the array of interfaces.
I would like to support this:
str, num, str2 = SetParams(params, args)
instead of having to do this:
values := SetParams([]interface{str, num, str2}, args)
str = values[0].(string)
num = values[1].(int)
str = values[2].(string)
Any advice? Help?
Please don't write horrible (and ineffective due to reflect) code to solve nonexistent problem.
As was indicated in comments, turning a language into
one of your previous languages is indeed compelling
after a switch, but this is counterproductive.
Instead, it's better to work with the idioms and approaches
and best practices the language provides --
even if you don't like them (yet, maybe).
For this particular case you can roll like this:
Make the function which wants to accept
a list of parameters with default values
accept a single value of a custom struct type.
For a start, any variable of such type, when allocated,
has all its fields initialized with the so-called "zero values"
appropriate to their respective types.
If that's enough, you can stop there: you will be able
to pass values of your struct type to your functions
by producing them via literals right at the call site --
initializing only the fields you need.
Otherwise have pre-/post- processing code which
would provide your own "zero values" for the fields
you need.
Update on 2016-08-29:
Using a struct type to simulate optional parameters
using its fields being assigned default values which happen
to be Go's native zero values for their respective data types:
package main
import (
"fmt"
)
type params struct {
foo string
bar int
baz float32
}
func myfun(params params) {
fmt.Printf("%#v\n", params)
}
func main() {
myfun(params{})
myfun(params{bar: 42})
myfun(params{foo: "xyzzy", baz: 0.3e-2})
}
outputs:
main.params{foo:"", bar:0, baz:0}
main.params{foo:"", bar:42, baz:0}
main.params{foo:"xyzzy", bar:0, baz:0.003}
As you can see, Go initializes the fields of our params type
with the zero values appropriate to their respective types
unless we specify our own values when we define our literals.
Playground link.
Providing default values which are not Go-native zero values for
the fields of our custom type can be done by either pre-
or post-processing the user-submitted value of a compound type.
Post-processing:
package main
import (
"fmt"
)
type params struct {
foo string
bar int
baz float32
}
func (pp *params) setDefaults() {
if pp.foo == "" {
pp.foo = "ahem"
}
if pp.bar == 0 {
pp.bar = -3
}
if pp.baz == 0 { // Can't really do this to FP numbers; for demonstration purposes only
pp.baz = 0.5
}
}
func myfun(params params) {
params.setDefaults()
fmt.Printf("%#v\n", params)
}
func main() {
myfun(params{})
myfun(params{bar: 42})
myfun(params{foo: "xyzzy", baz: 0.3e-2})
}
outputs:
main.params{foo:"ahem", bar:-3, baz:0.5}
main.params{foo:"ahem", bar:42, baz:0.5}
main.params{foo:"xyzzy", bar:-3, baz:0.003}
Playground link.
Pre-processing amounts to creating a "constructor" function
which would return a value of the required type pre-filled
with the default values your choice for its fields—something
like this:
func newParams() params {
return params{
foo: "ahem",
bar: -3,
baz: 0.5,
}
}
so that the callers of your function could call newParams(),
tweak its fields if they need and then pass the resulting value
to your function:
myfunc(newParams())
ps := newParams()
ps.foo = "xyzzy"
myfunc(ps)
This approach is maybe a bit more robust than post-processing but
it precludes using of literals to construct the values to pass to
your function right at the call site which is less "neat".
Recently I was playing with anonymous functions in Go and implemented an example which accepts and returns undefined parameters:
func functions() (funcArray []func(args ... interface{}) (interface{}, error)) {
type ret struct{
first int
second string
third bool
}
f1 := func(args ... interface{}) (interface{}, error){
a := args[0].(int)
b := args[1].(int)
return (a < b), nil
}
funcArray = append(funcArray , f1)
f2 := func(args ... interface{}) (interface{}, error){
return (args[0].(string) + args[1].(string)), nil
}
funcArray = append(funcArray , f2)
f3 := func(args ... interface{}) (interface{}, error){
return []int{1,2,3}, nil
}
funcArray = append(funcArray , f3)
f4 := func(args ... interface{}) (interface{}, error){
return ret{first: 1, second: "2", third: true} , nil
}
funcArray = append(funcArray , f4)
return funcArray
}
func main() {
myFirst_Function := functions()[0]
mySecond_Function := functions()[1]
myThird_Function := functions()[2]
myFourth_Function := functions()[3]
fmt.Println(myFirst_Function(1,2))
fmt.Println(mySecond_Function("1","2"))
fmt.Println(myThird_Function())
fmt.Println(myFourth_Function ())
}
I hope it helps you.
https://play.golang.org/p/d6dSYLwbUB9

Return values of function as input arguments to another

If I have
func returnIntAndString() (i int, s string) {...}
And I have:
func doSomething(i int, s string) {...}
Then I can do the following successfully:
doSomething(returnIntAndString())
However, let's say I want to add another argument to doSomething like:
func doSomething(msg string, i int, s string) {...}
Go complains when compiling if I call it like:
doSomething("message", returnIntAndString())
With:
main.go:45: multiple-value returnIntAndString() in single-value context
main.go:45: not enough arguments in call to doSomething()
Is there a way to do this or should I just give up and assign the return values from returnIntAndString to some references and pass msg and these values like doSomething(msg, code, str) ?
It's described here in the spec. It requires the inner function to return the correct types for all arguments. There is no allowance for extra parameters along with a function that returns multiple values.
As a special case, if the return values of a function or method g are
equal in number and individually assignable to the parameters of
another function or method f, then the call f(g(parameters_of_g)) will
invoke f after binding the return values of g to the parameters of f
in order. The call of f must contain no parameters other than the call
of g, and g must have at least one return value. If f has a final ...
parameter, it is assigned the return values of g that remain after
assignment of regular parameters.
func Split(s string, pos int) (string, string) {
return s[0:pos], s[pos:]
}
func Join(s, t string) string {
return s + t
}
if Join(Split(value, len(value)/2)) != value {
log.Panic("test fails")
}
If those specific conditions are not met, then you need to assign the return values and call the function separately.
I had the same question. The best solution I could come up with is creating types or structs for my desired extra parameters and writing methods for them like this:
package main
import (
"fmt"
)
type Message string
type MessageNumber struct {
Message string
Number int
}
func testfunc() (foo int, bar int) {
foo = 4
bar = 2
return
}
func (baz Message) testfunc2(foo int, bar int) {
fmt.Println(foo, bar, baz)
}
func (baz MessageNumber) testfunc3(foo int, bar int) {
fmt.Println(foo, bar, baz.Number, baz.Message)
}
func main() {
Message("the answer").testfunc2(testfunc())
MessageNumber{"what were we talking about again?", 0}.testfunc3(testfunc())
fmt.Println("Done. Have a day.")
}
The output looks like this:
user#Frodos-Atari-MEGA-STE:~/go/test$ go run main.go
4 2 the answer
4 2 0 what were we talking about again?
Done. Have a day.

Golang : Variable argument

When I compile the following program
func myPrint(v ...interface{}) {
fmt.Println("Hello", v...)
}
func main() {
myPrint("new", "world")
}
I get a compilation error
too many arguments in call to fmt.Println
I thought v... is going to expand into 2nd, 3rd arguments and the fmt.Println would see three item variadic argument list. I thought it would be equivalent to
fmt.Println("Hello", "new", "world")
Why is it giving an error.
Try this. It prepends Hello to the variadic arguments, then prints them all at once with println.
package main
import "fmt"
func myPrint(v ...interface{}) {
a := append([]interface{}{"Hello"}, v...) // prepend "Hello" to variadics
fmt.Println(a...) // println the whole lot
}
func main() {
myPrint("new", "world")
}
You're mis-using the variadic shorthand in your call to fmt.Println(). What you're actually sending is 2 arguments: a single string, then the slice of type interface{} expanded. The function call will not concatenate that into a single slice.
This design will compile and run with the results you're expecting:
func myPrint(v ...interface{}) {
fmt.Print("Hello ")
fmt.Println(v...)
}
func main() {
myPrint("new", "world")
}

Resources