To close this chapter off with a bang, we will implement a mechanism in which each Avatar
implementation takes a turn in trying to get the value. If the first implementation returns the ErrNoAvatarURL
error, we will try the next and so on until we find a useable value.
In avatar.go
, underneath the Avatar
type, add the following type definition:
type TryAvatars []Avatar
The TryAvatars
type is simply a slice of Avatar
objects; therefore, we will add the following GetAvatarURL
method:
func (a TryAvatars) GetAvatarURL(u ChatUser) (string, error) { for _, avatar := range a { if url, err := avatar.GetAvatarURL(u); err == nil { return url, nil } } return "", ErrNoAvatarURL }
This means that TryAvatars
is now a valid Avatar
implementation and can be used in place of any specific implementation. In the preceding method, we iterated over the slice of Avatar
objects in an order, calling GetAvatarURL
for each one. If no error is returned, we return the URL; otherwise, we carry on looking. Finally, if we are unable to find a value, we just return ErrNoAvatarURL
as per the interface design.
Update the avatars
global variable in main.go
to use our new implementation:
var avatars Avatar = TryAvatars{ UseFileSystemAvatar, UseAuthAvatar, UseGravatar}
Here we created a new instance of our TryAvatars
slice type while putting the other Avatar
implementations inside it. The order matters since it iterates over the objects in the order in which they appear in the slice. So, first our code will check to see whether the user has uploaded a picture; if they haven't, the code will check whether the authentication service has a picture for us to use. If both the approaches fail, a Gravatar URL will be generated, which in the worst case (for example, if the user hasn't added a Gravatar picture), will render a default placeholder image.
To see our new functionality in action, perform the following steps:
go build –o chat ./chat –host=:8080
http://localhost:8080/logout
.avatars
folder.http://localhost:8080/chat
.http://localhost:8080/upload
and upload a new profile picture.