How do I define a static member function? - oop

I'm using golang to build a web server. And I'm using the MVC architecture.
Now I don't know how to make the static member function.
For example, I've a struct User as one of my models:
type User struct{
name string
password string
}
Obviously, I need also the functions as below:
func (user User)addUser(){
conn := ConnToDB()
query = "insert into user (name, password) values ('" + user.name + "', '" + user.password + "');"
conn.execute(query)
}
func (user User)changeNameById(id int){
...
}
However, I don't know how to make a function to list all names. In Java or Python, such a function should be a static member function of the class User, in this case we can call the function like this:
User.listNames();
How to do the same thing in golang?

You simply write a regular function, not a member function:
func listUserNames() []string {
...
}
When calling it from your package, it will simply be listUserNames()
When calling it from outside your package, it will be prefixed by your package's name. (Also, you will have to make the function public in order to call it from another package)

Related

Would it be possible to call a Kotlin function with named parameters from Groovy (including `copy`)?

Context - a Kotlin codebase with Spock/Groovy tests.
In my Groovy tests it would be convenient to call Kotlin functions with named parameters using the names. I use this particularly for test builders for entities.
I'd like to be able to call them with parameter names from Groovy.
So given this Kotlin:
data class User(
val id: Id,
val name: String,
val emailAddress: String,
)
fun buildUser(
id: Id = randomId(),
name: String = randomName(),
emailAddress: String = randomEmailAddress(),
): User
I'd like to be able to write this groovy:
User user = buildUser(
name: 'My name'
)
It feels like this should be possible; either using a compiler plugin on the Kotlin side to overload the buildUser method with a version that takes a Map, or via an AST transform on the Groovy side. Has anyone done this?
This might also allow calling the copy method on a data class in the same way:
User user = buildUser()
User userWithDifferentEmailAddress = user.copy(emailAddress: 'me#example.com')
Ideally IntelliJ IDEA would know about it enough to be able to respect renaming parameters and navigate from call site parameter name to receiver site parameter, but that might be asking too much...
EDIT - looking at the decompiled Kotlin it creates the following methods:
public static User buildUser$default(Id var0, String var1, String var2, int var3, Object var4) {
// uses var3 as a flag to indicate which fields were provided by the caller
}
public static User copy$default(User var0, Id var1, String var2, String var3, int var4, Object var5) {
// uses var4 as a flag to indicate which fields were provided by the caller
}
so it should be possible to wrangle Groovy to call them, I think...
I can only offer a partial solution. With Groovy's #NamedVariant transformation you can declare your factory function like this in Groovy.
#NamedVariant
User buildUser(
Id id = randomId(),
String name = randomName(),
String emailAddress = randomEmailAddress()) {
new User (id, name, emailAddress )
}
and it will generate an overload that takes a map or parameters, so you can use them like you described.
As for the copy there is nothing to do in plain groovy.
You can try to write an AST Transform, but you'll be relying on the kotlin compiler implementation of how the method is generated and how to set the flags. I think it would be more easier to try to generate a custom groovy extension function that duplicates the copy behavior. See extension modules

Kotlin - Extension for final class

Is it possible to create extension of final classes like String? Like in swift it is possible to add additional methods inside a extension of final class.
For an example - I would like to create a method in String extension which will tell me String have valid length for password.
val password : String = mEdtPassword!!.getText().toString()
// how to define haveValidLength method in extension
val isValid : Boolean = password.haveValidLength()
Note - That example is just for a sake to understand usability of extension, not a real scenario.
yes, you can. Kotin extension method provides the ability to extend a class with new functionality without having to inherit from the class or use any type of design pattern such as Decorator.
Below is an extension method for a String:
// v--- the extension method receiver type
fun String.at(value: Int) = this[value]
And the extension method code generated as Java below:
public static char at(String receiver, int value){
return receiver.charAt(value);
}
So an extension method in Kotlin is using delegation rather than inheritance.
Then you can calling an extension method like as its member function as below:
println("bar".at(1))//println 'a'
You also can write an extension method for the existing extension function, for example:
fun String.substring(value: Int): String = TODO()
// v--- throws exception rather than return "ar"
"bar".substring(1)
But you can't write an extension method for the existing member function, for example:
operator fun String.get(value: Int): Char = TODO()
// v--- return 'a' rather than throws an Exception
val second = "bar"[1]
Trying to add more detail, this answer might be helpful for someone.
Yes we can add additional methods to final classes like String. For an example I would like to add one method in String which will tell me that my String have valid number of characters for password or not.
So what I have to do is, I have ti create a below function which can be written in same class or at different separate class file.
fun String.hasValidPassword() : Boolean {
// Even no need to send string from outside, use 'this' for reference of a String
return !TextUtils.isEmpty(this) && this.length > 6
}
And now from anywhere call
val isValid : Boolean = password.haveValidLength()
Suggestion
If your application just has a single password validation, then there is no problem.
However, I don't suggest you write such a extension method hasValidPassword if the application has more than one validation. since the extension method is satically, you can't change your hasValidPassword in runtime. So if you want to change the validation in runtime, you should using a function instead, for example:
class PasswordRepository(private val validate:(String)->Boolean){
fun save(value:String){
if(validate(value)){
//TODO persist the password
}
}
}
val permitAll = PasswordRepository {true}
val denyAll = PasswordRepository {false}
permitAll.save("it will be persisted")
denyAll.save("it will not be persisted")
In other words, the extension method above violates Single Responsibility Principle, it does validation & string operations.
You can do that with extension functions in Kotlin. With extensions, you are able to add extra functionality to a class that you do or do not have access to; for example a legacy code base. In the example given in the Kotlin docs here, swap was added to MutableList<Int> which doesn't have swap originally. A this keyword is used that refers to the object that the swap functionality will operate on. In the example below, this refers to testList
val testList = mutableListOf(1, 2, 3)
testList.swap(0, 2)

Is it bad to use a struct and treat it like a class to solve the dependency in Golang?

I wrote a lot PHP with the OOP frameworks before, and I'm learning Golang,
When I was using PHP, The class is useful that I could pass a $model in to my class then share it between functions:
class User {
function __construct(UserModel $model) {
$this->model = $model
}
function delete($id) {
$this->model->delete($id);
}
function update($id) {
$this->model->update($id);
}
}
$UserModel = new UserModel();
$User = new User($UserModel);
$User->delete(1);
But there's no class in Golang, I knew that I could treat structs like a class:
type User struct {
model *models.User
}
func (u *User) Delete(id int) {
u.model.Delete(id)
}
func (u *User) Update(id int) {
u.model.Update(id)
}
userModel := &models.User{}
user := User{model: userModel}
user.Delete(1)
I felt like the struct is used to store the information, and the method of the struct should be used to modify the value of the struct.
But right now I made a struct just because I want to treat it like a class and solve the dependency problem, is it bad to use such approach in Golang?
From overall conceptual standpoint there is nothing wrong in your implementation.
On a detailed view there are inconsistencies that raise questions.
In all cases below there is a potential concurrency issue due to data shared across various Delete calls.
Case A
If models.User{} does all the work, then why can't we just
userModel := &models.User{}
userModel.Delete(userId)
Case B
If User is our public interface:
user := User{model: userModel}
user.Delete(1)
then taking userId to delete is redundant and shall be done as:
user.Delete()
userId is taken from user context.
Case C
Otherwise, we might want to make userModel to be set for all User instances:
package User;
// private package level variable
var model = userModel
func Delete(userId int) {
model.Delete(userId)
}
...
User.Delete(userId)
Conclusion
Each case above solves the same problem with a slightly different emphasis. Case A is straightforward. Case B and C rely on underlying shared code that could be used with event notifications. Case B and C are different in User scope. In Case B User is a structure. In Case C user is a package name. I think Case C is used less often than Case B. So, if use insist on having an underlying model, then Case B is probably the most intuitive solution from user code point of view.
you can use interface with method
In service (connect db)
// UserServiceInterface include method list
type UserServiceInterface interface {
GetAll(helpers.ParamsGetAll) (models.PublicUsers, error)
Get(int64) (models.User, error)
Delete(int64) (bool, error)
Create(models.User) (int64, error)
Update(models.User) (models.User, error)
CheckExistUsername(string) (bool, error)
CheckExistEmail(string) (bool, error)
CreateEmailActive(string, string, int64) error
CheckExistUser(int64) (bool, error)
}
// UserService struct
type userService struct{}
// NewUserService to constructor
func NewUserService() userService {
return userService{}
}
func (userService )GetAll (p helpers.ParamGetAll)(models.PublicUser, error) {
code here....
}
In user controller
// UserController controller
type UserController struct {
Service services.UserServiceInterface
}
func (controller UserController) GetAll(c *gin.Context) {
users, errGetAll := controller.Service.GetAll(params)
}

Why is it possible to export variable of private type

Think like this :
package first
type person struct {
Name string
}
var Per = person{
Name: "Jack",
}
and in main package
package main
import "first"
import "fmt"
func main(){
o := first.Per
fmt.Println(o)
}
the above works, as we can see that the variable in first package was visible outside but it's type was not, but it gives no error? And how it can be useful outside package?
it is fine:
Exported identifiers:
An identifier may be exported to permit access to it from another
package. An identifier is exported if both:
the first character of the identifier's name is a Unicode upper case
letter (Unicode class "Lu"); and
the identifier is declared in the
package block or it is a field name or method name. All other
identifiers are not exported.
ref: https://golang.org/ref/spec
and even you can use Getters:
Go doesn't provide automatic support for getters and setters. There's
nothing wrong with providing getters and setters yourself, and it's
often appropriate to do so, but it's neither idiomatic nor necessary
to put Get into the getter's name. If you have a field called owner
(lower case, unexported), the getter method should be called Owner
(upper case, exported), not GetOwner. The use of upper-case names for
export provides the hook to discriminate the field from the method. A
setter function, if needed, will likely be called SetOwner. Both names
read well in practice:
owner := obj.Owner()
if owner != user {
obj.SetOwner(user)
}
ref: https://golang.org/doc/effective_go.html
so if you do not want to export Name make it lower case, like this working sample codes and use Getter/Setter :
package first
type person struct {
name string
}
var Per = person{
name: "Jack",
}
func (p *person) SetName(name string) {
p.name = name
}
func (p *person) Name() string {
return p.name
}
main.go (with commented output):
package main
import "first"
import "fmt"
func main() {
person := first.Per
fmt.Println(person.Name()) //Jack
person.SetName("Alex")
fmt.Println(person.Name()) //Alex
}
another use cases:
Singleton pattern
Essentially, it's a singleton pattern. The package exports a single instance of person but because the type is private you can't create another instance out of it.
Better implementation would be to export a function that returns a singleton instance of a private type. On first invocation it will create the instance in a thread-safe manner.
var (
p *person
once sync.Once
)
type person struct {
Name string
}
func Per() *person {
once.Do(func() {
p = &person{
Name: "Jack",
}
})
return p
}
sync.Once allows you to execute a piece of code only once even if multiple goroutines are trying to execute it.

AspectJ OR Operator Doesn't Seem to be Functioning

I'm having a little trouble getting a logging aspect set up using SpringAOP + AspectJ. I would like an "Around" method to fire when either a class or method is annotated with the #Loggable annotation. Below is my advice code:
#Around(value = "execution( * *(..)) && target(bean) && #annotation(loggable)", argnames "bean, loggable")
public void test1(ProceedingJoinPoint method, Object bean, Loggable loggable) { }
#Around(value = "execution( * *(..)) && target(bean) && #within(loggable)", argnames "bean, loggable")
public void test2(ProceedingJoinPoint method, Object bean, Loggable loggable) { }
#Around(value = "execution( * *(..)) && target(bean) && (#annotation(loggable) || #within(loggable))", argnames "bean, loggable")
public void test3(ProceedingJoinPoint method, Object bean, Loggable loggable) { }
test1 and test2 fire. test3 does not, and it's the one that I really want. Any thoughts on why this might be?
First of all, there are syntax errors in your pointcuts. It is not lower-case argnames but argNames and you are missing an = in between parameter name and value. So it must be argNames = "bean, loggable".
Secondly if your advice returns void it will only match methods returning void as well. The more general case is to return Object in the advice to really match all methods.
Last but not least, you should see a warning which explains the problem with the third pointcut. This is displayed in your Eclipse IDE or on the AspectJ compiler's (ajc) log output:
ambiguous binding of parameter(s) loggable across '||' in pointcut
This means that you cannot say "bind one value or the other to the parameter 'loggable'". What if both conditions match? Which one should be assigned? You have two options, assuming your fully-qualified class name is de.scrum_master.app.Loggable:
A) No reference to #Loggable annotation needed:
This is the simple case. If #Loggable does not have any parameters you need to read, it is not necessary to bind it to a parameter. BTW, if you want your pointcut to also capture static methods, you should not bind target() either because the target would be null. Maybe in Spring-AOP this is irrelevant because it only works with Spring Beans anyway, but in full-featured AspectJ it would make a difference because it is more powerful.
#Around(value = "execution(* *(..)) && (#annotation(de.scrum_master.app.Loggable) || #within(de.scrum_master.app.Loggable))")
public Object withoutLoggableReference(ProceedingJoinPoint thisJoinPoint) {
Object bean = thisJoinPoint.getTarget();
System.out.println(thisJoinPoint + " -> " + bean);
return thisJoinPoint.proceed();
}
Or, equivalently:
#Around(value = "execution(* (#de.scrum_master.app.Loggable *.*)(..)) || execution(#de.scrum_master.app.Loggable * *.*(..))")
public Object withoutLoggableReference(ProceedingJoinPoint thisJoinPoint) {
Object bean = thisJoinPoint.getTarget();
System.out.println(thisJoinPoint + " -> " + bean);
return thisJoinPoint.proceed();
}
B) Reference to #Loggable annotation needed:
You have no other choice than to go with two separate pointcuts if you want to bind the annotations to parameters. Maybe you could use a utility method doing the actual logging in order to avoid code duplication in your advice.