I have a program that requires either 1 or 2 arguments depending on what the users wants to run
var (
clientSet = tools.NewClientSet(os.Args[2])
)
func main {
if os.Args[1] == "validate" {
// run validate function, no need for user to have os.Args[2]
}else if os.Args[1] == "sync" {
// run sync function that requires os.Args[2]
}
}
func foo{
tools.Manage(clientSet)
}
I need the clientSet variable to be global, but I dont need the users to have os.Args[2] if the users only wants to use the validate function. Putting the clientSet function inside main() will make my foo() function broken and I can't declare a variable with an empty value.
So I want my users to be able to run go run main.go validate and go run main.go sync production smoothly.
*production is an arbitrary value
I could have my users to run go run main.go validate _ to plug this problem, but that would be inelegant.What's the best way to tackle this problem?
I don't even see the need for a global variable in this case. You can just make the sync function accept a ClientSet e.g. func sync(c ClientSet). But if you really need the global variable then you should not do this unless you want your program to panic when there are no arguments present.
var (
clientSet = tools.NewClientSet(os.Args[2])
)
What you should do is to assign it a default value or the zero value of your type.
var (
clientSet tools.ClientSet
)
Your main function would look somewhat like this:
var (
clientSet tools.ClientSet
)
func main() {
if len(os.Args) < 2 {
os.Exit(1)
}
switch os.Args[1] {
case "validate":
validate()
case "sync":
if len(os.Args) < 3 {
os.Exit(1)
}
clientSet = tools.NewClientSet(os.Args[2])
sync()
default:
// place your default case here
}
}
Still, I suggest you just pass a ClientSet to the sync function since it will avoid global variables.
The answer is often to not use globals. Instead have foo take an argument foo(clientSet ClientSet) and instantiate it only if you need to.
Just use len(os.Args) function
var (
clientSet tools.ClientSet
)
func main() {
if len(os.Agrs) == 1 {
// just the file name
} else if len(os.Args) == 2 {
if os.Args[1] == "validate" {
// run validate function, no need for user to have os.Args[2]
} else if os.Args[1] == "sync" {
// sync with no argument show error
}
} else if len(os.Args) == 3 {
if os.Args[1] == "validate" {
clientSet = tools.NewClientSet(os.Args[2])
} else {
// non validate with the second arg
}
} else {
// else, if required
}
}
Atlhough I would suggest you to NOT to use global variables. Avoid if possible.
Related
There are several switches in the app's layout, and when these switches are pressed, the value of sharedPreference is changed to determine whether a specific function is performed. For example, if the funcOnOff switch is off, the voice notification function is off, and when fromOnOff is off, caller information cannot be checked when a notification is received.
I am using several source codes that work almost similarly as below. Is it possible to pass multiple android.widgets as parameters to a function so that these actions can be acted upon as a single function?
var funcOnOff: Switch = findViewById(R.id.func_on_off)
var fromOnOff: Switch = findViewById(R.id.from_on_off)
var timeOnOff: Switch = findViewById(R.id.time_on_off)
var contentOnOff: Switch = findViewById(R.id.content_on_off)
funcOnOff.setOnCheckedChangeListener { buttonView, isChecked ->
if (isChecked) {
editor.putString("func", "ON")
} else {
editor.putString("func", "OFF")
}
editor.commit()
}
fromOnOff.setOnCheckedChangeListener { buttonView, isChecked ->
if (isChecked) {
editor.putString("from", "ON")
} else {
editor.putString("from", "OFF")
}
editor.commit()
}
timeOnOff.setOnCheckedChangeListener { buttonView, isChecked ->
if (isChecked) {
editor.putString("time", "ON")
} else {
editor.putString("time", "OFF")
}
editor.commit()
}
If I understand correctly, you can make a factory method for the OnCheckedChangeListeners.
fun onCheckedChangedListenerForPreferenceKey(key: String): CompoundButton.OnCheckedChangeListener = { _, isChecked ->
if (isChecked) {
editor.putString(key, "ON") // wouldn't using putBoolean be better?
} else {
editor.putString(key, "OFF")
}
editor.commit()
}
Then you can do:
funcOnOff.setOnCheckedChangeListener(onCheckedChangedListenerForPreferenceKey("func"))
fromOnOff.setOnCheckedChangeListener(onCheckedChangedListenerForPreferenceKey("from"))
timeOnOff.setOnCheckedChangeListener(onCheckedChangedListenerForPreferenceKey("time"))
Or you can make a list of pairs of switches to preference keys, and iterate through them:
listOf(
funcOnOff to "func"
fromOnOff to "from"
timeOnOff to "time"
).forEach { (switch, key) ->
switch.setOnCheckedChangeListener(onCheckedChangedListenerForPreferenceKey(key))
}
As a general alternative to Sweeper's answer - most widget listeners (and a lot of other UI callbacks in Android) pass in the object that generated the event as a parameter. So you can create a function that checks that parameter, and acts accordingly:
// If the signature here matches the listener function, you can pass a reference
// to this function directly
fun handleSwitch(switch: CompoundButton, isChecked: Boolean) {
when(switch) {
funcOnOff -> "func"
fromOnOff -> "from"
timeOnOff -> "time"
else -> null
}?.let { key ->
editor.putString(key, if (isChecked) "ON" else "OFF").commit()
}
}
Then you can just apply that to all your switches:
val switches = listOf(funcOnOff, fromOnOff, timeOnOff)
switches.forEach { it.setonOnCheckedChangedListener(::handleSwitch) }
// or if you don't want to use a function reference
switches.forEach {
it.setOnCheckedChangedListener { switch, enabled -> handleSwitch(switch, enabled) }
}
// or since you're iterating over the switches anyway, you could make the current one
// part of the callback lambda and ignore the parameters
switches.forEach { switch ->
it.setOnCheckedChangedListener { _, _ -> handleSwitch(switch, switch.isChecked) }
}
You get the idea! Personally I feel like passing a function reference is neater, instead of creating a separate lambda for each switch, but honestly it depends - no need to overcomplicate things if a neat one-liner setup will get the job done!
Also personally I'd probably use a Map instead of the when, like in Sweeper's answer - that way you can define the switches in use and their keys in one place, and then you can assign your listeners by iterating over the map's keys. No repeating yourself by listing the keys in one place, and then again in the when, y'know? Easier to maintain too, you might forget to update one of those places - but this is just a general example!
Essentially this is in the title. I have a value that could be null. If it is, I just want to exit with a message. If it's not null, then there's a whole slew of work I need to do with this value.
I've found similar, but not quite this exact situation. And it's the subtle difference that's driving me nuts. Here is my code in java:
if (value == null) {
print("error!");
return;
}
print(value);
doFunStuff(value);
etc(value);
All those methods using value require it to be non-null.
But I'm having a difficult time figuring this out in kotlin. With everything I try, the compiler still insists that value is still nullable and refuses to use it in the functions.
What is the kotlin way of doing this very common code flow?
If your methods truly have non-null parameters, the Kotlin compiler should be smart enough to do a smart cast to Object from Object?.
fun yourMethod(value: Object?) {
if (value == null) {
print("error!")
return
}
print(value) // Smart cast happens here
doFunStuff(value)
etc(value)
}
fun print(value: Object) {
// Implementation
}
fun doFunStuff(value: Object) {
// Implementation
}
fun etc(value: Object) {
// Implementation
}
But you can also force the conversion by using the !! operator (though in this case the compiler will tell you it's not necessary):
fun yourMethod(value: Object?) {
if (value == null) {
print("error!")
return
}
val nonNullValue = value!!
print(nonNullValue)
doFunStuff(nonNullValue)
etc(nonNullValue)
}
fun print(value: Object) {
// Implementation
}
fun doFunStuff(value: Object) {
// Implementation
}
fun etc(value: Object) {
// Implementation
}
If your value is a local variable or a function parameter, you won't have this problem, because the compiler will smart-cast it to not-null.
So, I'm assuming value in this case is a member property.
Option 1 is to copy it to a local variable to use in the function:
val value = value
if (value == null) {
print("error!")
return
}
print(value)
doFunStuff(value)
etc(value)
Option 2 is to use the let or also scope functions to do the same thing, but this might not be a good option here because so much code would become nested. This is more useful when you're only calling one or two functions with the object, in which case, you wouldn't even have to name it (just call it it).
value.let { value ->
if (value == null) {
print("error!")
return
}
print(value)
doFunStuff(value)
etc(value)
}
If your entire function works with this one property, you can avoid the nesting problem like this, if you don't mind it returning something besides Unit:
fun foo() = value.also { value ->
if (value == null) {
print("error!")
return
}
print(value)
doFunStuff(value)
etc(value)
}
Option 3 is to assert non-null every time you use it, but this is very ugly. This is only safe if you know the property is only ever accessed from the same thread this function is ever called on.
if (value == null) {
print("error!")
return
}
print(value!!)
doFunStuff(value!!)
etc(value!!)
Expanding on #Mehul's answer, this would only run the code in the let if the value was not null. If null, you could run the outside process and return from it.
value?.let { nonNullValue ->
print(nonNullValue);
doFunStuff(nonNullValue);
etc(nonNullValue);
}?: run { print("error!") ; return }
That said, since you are no longer needing the return to abort the function if null, you could simply do this and further clean it up replacing the lambda.
value?.let {
print(it);
doFunStuff(it);
etc(it);
}?: print("error!")
Well, have you already tried something like this and this is not what you expect?
value?.let { nonNullValue ->
print(nonNullValue);
doFunStuff(nonNullValue);
etc(nonNullValue);
}
basically the code inside let block will run only if the value isn't null.
How to return from an anonymous lambda in Kotlin?
Somehow the complier doesn't allow to return inside the lambda body. Since the lambda is anonym an return#... isn't possible here.
class Foo {
var function: (String) -> Unit = { _ -> }
init {
function = { text ->
if (text == "foo"){
// do side effects here
return
//'return' is not allowed here
//This function must return a value of type Foo
}
// do side other side effects
}
}
}
EDIT: update the example so it is clear that this question is about the return statement and not coding practices
Use Label:
class Foo {
var function: (String) -> Unit
init {
function = function# { text ->
if (text == "foo"){
return#function
}
print(text)
}
}
}
While it's possible to do, I'm not a fan of that sort of thing and prefer to restructure the flow when practical. In your example, it would be something like:
function = { text ->
if (text == "foo"){
// do side effects here
} else {
// do side other side effects
}
}
There are usually ways to keep the flow to a single return path, so you don't have to do strange things like have multiple return statements or use labels.
In Obj-C, I could define a macro
#define check_nil(x) if (!x) { return nil }
which can be used to test whether a function has returned nil (indicating an error), and if that's the case, the caller can simply return nil -- propagating the error up the stack. I am writing a parser, and this pattern happens very often. E.g.
- (id)caller {
...
id z = [self callee];
check_nil(z);
...
}
- (id)callee {
...
}
Unfortunately, after moving to swift, macros are gone. Function (with #autoclosure) are to replace them, but not in this case. Now my code is littered with identical if checks.
Any idea to replicate the same thing in Swift?
You are not going to be able to implement that pattern exactly.
Perhaps you could use a type that will turn future operations into no-ops if they ever return nil:
struct NonNil<T> {
var cantBeNil: T?
mutating func update(withClosure: () -> T?) {
if self.cantBeNil != nil {
self.cantBeNil = withClosure()
}
}
}
Then you can use this struct like so:
func myFunc() -> String? {
var nonNil = NonNil(cantBeNil: "")
nonNil.update {
// some action
return "new value"
}
nonNil.update {
// another action that ends up returning nil
return nil
}
// The rest of these don't end up calling the closure
nonNil.update {
println("not called")
return ""
}
nonNil.update {
println("not called")
return ""
}
return nonNil.cantBeNil
}
The idea being that if any operation returns nil, the rest of the code will fall through until the return statement, not executing any additional operations.
This will also visually separate all of the parts of the code that can cause the value to be set to nil
Given this code
func doomed() {
os.Exit(1)
}
How do I properly test that calling this function will result in an exit using go test? This needs to occur within a suite of tests, in other words the os.Exit() call cannot impact the other tests and should be trapped.
There's a presentation by Andrew Gerrand (one of the core members of the Go team) where he shows how to do it.
Given a function (in main.go)
package main
import (
"fmt"
"os"
)
func Crasher() {
fmt.Println("Going down in flames!")
os.Exit(1)
}
here's how you would test it (through main_test.go):
package main
import (
"os"
"os/exec"
"testing"
)
func TestCrasher(t *testing.T) {
if os.Getenv("BE_CRASHER") == "1" {
Crasher()
return
}
cmd := exec.Command(os.Args[0], "-test.run=TestCrasher")
cmd.Env = append(os.Environ(), "BE_CRASHER=1")
err := cmd.Run()
if e, ok := err.(*exec.ExitError); ok && !e.Success() {
return
}
t.Fatalf("process ran with err %v, want exit status 1", err)
}
What the code does is invoke go test again in a separate process through exec.Command, limiting execution to the TestCrasher test (via the -test.run=TestCrasher switch). It also passes in a flag via an environment variable (BE_CRASHER=1) which the second invocation checks for and, if set, calls the system-under-test, returning immediately afterwards to prevent running into an infinite loop. Thus, we are being dropped back into our original call site and may now validate the actual exit code.
Source: Slide 23 of Andrew's presentation. The second slide contains a link to the presentation's video as well.
He talks about subprocess tests at 47:09
I do this by using bouk/monkey:
func TestDoomed(t *testing.T) {
fakeExit := func(int) {
panic("os.Exit called")
}
patch := monkey.Patch(os.Exit, fakeExit)
defer patch.Unpatch()
assert.PanicsWithValue(t, "os.Exit called", doomed, "os.Exit was not called")
}
monkey is super-powerful when it comes to this sort of work, and for fault injection and other difficult tasks. It does come with some caveats.
I don't think you can test the actual os.Exit without simulating testing from the outside (using exec.Command) process.
That said, you might be able to accomplish your goal by creating an interface or function type and then use a noop implementation in your tests:
Go Playground
package main
import "os"
import "fmt"
type exiter func (code int)
func main() {
doExit(func(code int){})
fmt.Println("got here")
doExit(func(code int){ os.Exit(code)})
}
func doExit(exit exiter) {
exit(1)
}
You can't, you would have to use exec.Command and test the returned value.
Code for testing:
package main
import "os"
var my_private_exit_function func(code int) = os.Exit
func main() {
MyAbstractFunctionAndExit(1)
}
func MyAbstractFunctionAndExit(exit int) {
my_private_exit_function(exit)
}
Testing code:
package main
import (
"os"
"testing"
)
func TestMyAbstractFunctionAndExit(t *testing.T) {
var ok bool = false // The default value can be omitted :)
// Prepare testing
my_private_exit_function = func(c int) {
ok = true
}
// Run function
MyAbstractFunctionAndExit(1)
// Check
if ok == false {
t.Errorf("Error in AbstractFunction()")
}
// Restore if need
my_private_exit_function = os.Exit
}
To test the os.Exit like scenarios we can use the https://github.com/undefinedlabs/go-mpatch along with the below code. This ensures that your code remains clean as well as readable and maintainable.
type PatchedOSExit struct {
Called bool
CalledWith int
patchFunc *mpatch.Patch
}
func PatchOSExit(t *testing.T, mockOSExitImpl func(int)) *PatchedOSExit {
patchedExit := &PatchedOSExit{Called: false}
patchFunc, err := mpatch.PatchMethod(os.Exit, func(code int) {
patchedExit.Called = true
patchedExit.CalledWith = code
mockOSExitImpl(code)
})
if err != nil {
t.Errorf("Failed to patch os.Exit due to an error: %v", err)
return nil
}
patchedExit.patchFunc = patchFunc
return patchedExit
}
func (p *PatchedOSExit) Unpatch() {
_ = p.patchFunc.Unpatch()
}
You can consume the above code as follows:
func NewSampleApplication() {
os.Exit(101)
}
func Test_NewSampleApplication_OSExit(t *testing.T) {
// Prepare mock setup
fakeExit := func(int) {}
p := PatchOSExit(t, fakeExit)
defer p.Unpatch()
// Call the application code
NewSampleApplication()
// Assert that os.Exit gets called
if p.Called == false {
t.Errorf("Expected os.Exit to be called but it was not called")
return
}
// Also, Assert that os.Exit gets called with the correct code
expectedCalledWith := 101
if p.CalledWith != expectedCalledWith {
t.Errorf("Expected os.Exit to be called with %d but it was called with %d", expectedCalledWith, p.CalledWith)
return
}
}
I've also added a link to Playground: https://go.dev/play/p/FA0dcwVDOm7