Understanding io.Reader in Go

Recently, I was trying to learn how the io.Reader interface works in Go and implement my own custom reader. Before implementing a custom Reader let’s understand what they are.

Readers: What are they?

Readers are interfaces or classes that are implemented in various programming languages. Usually, readers take in an input interface that can usually be represented as an array and a length. The reader returns another stream that is usually a cut to the length of the original input. Readers are implemented in various programming languages as following:

  • Java: readers are implemented by the interface java.io.Reader that implements read(char[], int, int) and close().
  • C++: readers are implemented by the istream where the read function is depicted as follows istream& read (char* s, streamsize n);
  • Go: readers are implemented by the io.Reader interface which has Read(p []byte) error.

In the above examples, readers in various programming language do the same thing; they read from the input stream and make a copy of the same into the char / byte array that is provided to the Read function.

Implementing custom Reader in Go

In this example, we will implement a reader that will add the capitalize the characters in the resulting byte array to which we want to copy the result into.

Note: This may or may not be suitable for production but is an example. I have also not seen examples of modifying the string.

Readers in Go need to implement the following language

type Reader interface {
	Read(p []byte) (n int, err error)
}

We will use 2 ways to implement the reader:

  • By natively implementing the Read function.
  • Using an already existing reader (strings.Reader)

Native implementation of the Read function

package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"time"
)

// CapitalizeReader is a reader that implements io.Reader
// It read the bytes from a particular position and returns the number
// of bytes that are read. If an error is thrown, all the errors are thrown
// as it is.
type CapitalizeReader struct {
	b []byte
	i int
}

// Read implements the function for CapitalizeReader.
// p is the []byte where the data is copied to.
// n is the number of bytes that are read and if there is an error it is
// returned along with the bytes that are read.
func (cr *CapitalizeReader) Read(p []byte) (n int, err error) {
	// By default, the size of the
	// if the number of bytes are less than the bytes to be read, then we assign it.
	var l int = len(p)
	if len(cr.b)-cr.i < len(p) {
		l = len(cr.b) - cr.i
	}
	var t []byte = cr.b[cr.i : cr.i+l]
	n = copy(t, cr.b[cr.i:])
	cr.i += n
	t = bytes.ToUpper(t)
	n = copy(p, t)

	// If the bytes read is less than the length of input byte slice, return the number of bytes
	// and io.EOF; it is different from Go's byte reader implementation where it will copy everything
	// and always return 0, io.EOF in the next implementation.
	// Ref: https://golang.org/src/bytes/reader.go?s=1154:1204#L30
	if l < len(p) {
		return n, io.EOF
	}
	return n, nil
}

// NewCapitalizeReader takes in a string and returns a reader.
// Store string as a slice of bytes so that we can read bytes
// and uppercase it on read.
func NewCapitalizeReader(s string) *CapitalizeReader {
	return &CapitalizeReader{b: []byte(s), i: 0}
}

func main() {
	str := "hello world"
	cr := NewCapitalizeReader(str)

	fmt.Println("length of the string: ", str, " is ", len(str))
	var b = make([]byte, 2)

	for {
		time.Sleep(200 * time.Millisecond)
		n, err := cr.Read(b)
		fmt.Println(n, "\t", n, "\t", string(b[:n]))
		if err != nil {
			if err == io.EOF {
				break
			}
			log.Fatal(err)
		}
	}
	bytes.NewReader()
}

Using an already existing reader (strings.Reader)

The below example explains how to use an underlying Reader. Go does this quite often. For example, we have the LimitReader (https://golang.org/pkg/io/#LimitedReader). The LimitReader accepts a Reader and assigns this reader as the underlying reader. Once a set number of bytes are reached, it will return an EOF even if the underlying reader has not reached an EOF. This example uses strings.Reader as the underlying Reader.

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"log"
	"strings"
	"unicode"
)

// CapitalizeReader is a reader that implements io.Reader
// The underlying reader is a strings.Reader that is used to 
// read the bytes from a particular position and returns the number 
// of bytes that are read. All the errors are thrown
// as it is. 
type CapitalizeReader struct {
   // sr is the underlying reader to use the reading operations for.
	sr       *strings.Reader
   // offset is the index from where the string is read into the given []byte slice
	offset int64
}

// Read implements the function for CapitalizeReader
// p is the []byte where the data is copied to.
// n is the number of bytes that are read and if there is an error it is 
// returned along with the bytes that are read.
func (cr *CapitalizeReader) Read(p []byte) (n int, err error) {
   // create a new array where modifications will be made
	var t = make([]byte, len(p))
	n, err = cr.sr.ReadAt(t, cr.offset)
    // track the offset by number of bytes that were read
	cr.offset = cr.offset + int64(n)
	t = bytes.ToUpper(t)
    // copy to the provided array only when all the operations are done.
   //  io.Reader interface explicitly specifies that p should not be held by Read.
	copy(p, t)
    return
}

// NewCapitalizedReader takes in a string and returns a reader.
// offset is set to 0 as that is we want to read from.
func NewCapitalizeReader(s string) *CapitalizeReader {
	return &CapitalizeReader{sr: strings.NewReader(s), offset: 0}
}

func main() {
	str := "hello world"
	cr := NewCapitalizeReader(str)

	fmt.Println("length of the string: ", str, " is ", len(str))
	var b = make([]byte, 2)

	for {
		n, err := cr.Read(b)
        // Notice that we read by slice b[:n] even in the case of error
        //  This is because io.EOF can happen we can still have a byte that is read and 
        //  it is easy to miss it out.
		fmt.Println(n, "\t", n, "\t", string(b[:n]))
		if err != nil {
			if err == io.EOF {
               // exit gracefully with in case of io.EOF
				break
			}
           // For all other errors exit with a non-zero exit code.
			log.Fatal(err)
		}
	}
}

Summary

  1. Readers have a similar interface in various programming languages.
  2. Readers in Go can be implemented natively by implementing the Read(p []byte) (int, eror) method for any struct.
  3. Readers in Go can also have a backing or an underlying reader that can be used to implement a new reader. This new reader can be limit or enhance the capability of the underlying reader. An example of this is the LimitReader in Go

Advertisement

How my savings are affected on Jet when I buy more things from it?

Jet is an e-commerce competitor to Amazon. I have been using Jet as a service for some time now and really love it. As a user, I use Jet to buy my groceries and some small ingredients daily.

What attracted me to the Jet was its free delivery for 35$ without any need for the requirement for Amazon Prime. I figured that if I can avoid the subscription cost and I can still buy my stuff, hey why not?

What really kept me hooked on to Jet was these factors

  1. No subscription and free shipping for a base amount of purchase
  2. Discounts and savings
  3. An above average customer service.

As I use Jet more and more, I wanted to find out how my savings were affected over time. What I really wanted to know was if I as a user was saving more over time or less given its dynamic pricing.

I will make a few assumptions here:

  1. I will not include any discount coupons applied as not all orders had discounts (in fact, I had applied only 1 discount coupon).
  2. I will not include any shipping discounts applied as well.
  3. I will not include taxes applied as part of my purchase as well.
  4. To normalize, all my savings will be displayed as the % of the amount I bought.

This is what I found from my own purchase behavior.

chart.png

Observations

  1. As I buy more things on Jet, my savings on Jet.com go lower.
  2. There are peaks in the savings which help keep the users hooked into making purchases.

Takeaways from this for a customer acquisition and retention strategy

  1. First time users can be discounted heavily to make sure that they try the products for the first time.
  2. To build retention loops, the next few subsequent products can be discounted more than the first time so that users return to use their products in the hopes of gaining more values.
  3. As the users get used to the product, discounts can be reduced to recover the costs that were initially spent to acquire users.

 

7 cups of tea – Product review

Juggling between homework, working on my part time job and searching for a full time sums up my life. As I try to balance my life, there are slumps when I wished I had someone to vent out my frustrations to. But then, everyone is so busy that no one has time for anyone. If a friend has time to talk to you, can I be sure that they won’t judge you for having this super awkward conversation which no one wants to talk about? I can not be sure about this. I wished to have someone to talk outside my peer group, hopefully immediately without scheduling an appointment and without getting judged will provide a bit of support when I needed it the most.

After talking to my peers, I found out that I was not alone. A major portion of undergraduates and graduate students alike report mental stress or related issues because of increasing workloads. As they combat these mental and emotional stress, they want an outlet to vent out their feelings without being judged by their peers. Campus resources are inadequate as they are coupled with long waits. Students have to wait for weeks before making an appointment with the campus psychological services. During these wait times, if the issues are not solved, they get exacerbated.

This was when I was came across 7 Cups. 7 Cups is an on-demand emotional health and well-being service that connects people anonymously with trained listeners. By using this service, people can

  • talk to someone who will not know them
  • talk to groups of people anonymously who have faced the same problem regulated by a listener.
  • talk on various topics ranging from mental disorders to daily activities like College Life.
  • can get some help when they are waiting to be counselled by a professional counselor.

 


The ability to talk to people about various stress sources / mental disorders was incredibly useful. To validate my hypothesis that the application might be useful, I tried it a couple of times and spoke to a listener. I felt lighter and better after our conversation. So, I spoke to various students around the campus and see what they felt about handling stress. Out of the 18 students I spoke to, I received at least 3 or more students who shared that having an outlet will be useful.

Students quoted

[…]the times when I can’t get over the hump on my own, I wish I had someone there to give me just the motivation I needed.

It would  be nice to talk to people, but maybe not here

“Sleep helps, talking to people helps, putting things in perspective also helps.”

Help yourself section

7 cups also provides a set of resources for its users when they do not want to talk to anyone but are looking for specific strategies or resources that can help them manage their problems on their own.

The Help Yourself section provides

  1. a set of exercises that the users can use for self improvement
  2. forums where they can ask questions
  3. self-help guides that students can refer when they want to

 

 

Customized Portals

7 cups has customized portals that identifies the needs of specific communities. Identifying their needs is important as different communities will have different problems. Couples running households will have different problems and invariably face stress in a different form than teenagers. While the categories address that, 7 cups of Tea has extended the same notion beyond categories and come with customized portals.

They have launched a customized portal for startups where startups can talk to list for listeners who are trained to listen to entrepreneurs. Along with that,  they have customized resources where they can look for help that can improve their daily lives, relationships with families and friends across.

Directly quoted from their website, we find that even when entrepreneurs go through depression and other problems.

The ups and down of startups are often compared to a roller coaster. The downs can be really rough. Talking to others who have gone through what you are going through can really help. – JESSICA LIVINGSTON, Partner, Y Combinator

Most of my life I have struggled with depression. I’ve written about it, talked about it, coached and listed to others fighting with it. It’s a horrible isolating and debilitating condition. – Zak Homuth, Co-Founder & CEO, Upvert

My wish – Customized portals for Universities

Over the past few months, I have spoken to over 30 students by conducting formal interviews or randomly surveying them in the hallways, I have realized that there is an urgent need, and universities create a unique environment that contribute to stress for students.  Having customized portals for universities can go a long way in helping students combat daily emotional and mental sources of stress.

Research at the University of Michigan suggests that different student population react differently to stress. A study led by Prof. Daniel Eisenberg, approximately one-third of college students experience a mental health issue at some point. However, only 10 percent of student athletes with depression or anxiety take advantage of mental health resources – as compared to 30 percent of students overall.  Students at campuses often face different kind of stress that can be because of their academics, gender, sexual orientation, race etc.

Repeatedly, from the user interviews I conducted, I found that students needed an outlet to share their feelings. Customized portals for Universities will not only make listeners aware of the issues at the University, but will also help them tailor their conversational skills for the community groups. Additionally, universities can provide more training opportunities for students who are enrolled in their Social Work program to make them better future counselors.

Not only does it makes sense for 7 Cups to have separate portals for Universities, research shows that it makes business sense for Universities to trial run new emotional well being and mental wellness services. A revenue model developed by Prof. Eisenberg shows the potential loss for students who drop out of college because of stress and the loss in revenues. The example table at the end of the post shows that student productivity is lost valued at $3,125,000. The university fails to make an additional $ 1,562,500 revenue per year because of students dropping out.

There are other products like Breakthrough which provide confidential counselling, however 7 Cups differentiates themselves from other competitors by

  1. Pricing their product for free and opening up premium features at a very low cost (7.99$ / month for a year’s package).
  2. They provide active listening services and in no way a replacement to real counselling. The listeners are explicitly asked to not give advice, prescribe medicines to their clients and refer their clients to a counselor / psychiatrist in such cases.

On a concluding note, I find 7 cups a very interesting product in an interesting space, and is trying to solve a much needed problem that is often not realized or talked about in public spaces. By leveraging technology, 7 Cups can potentially change a lot of interactions in the mental health community.  Despite all of the positives, products like 7 Cups should be used with a pinch of salt. Users might not realize and start seeing their listeners as mental health providers. In this process, the users might start avoiding mental health providers and their issues can get worse. 7 Cups and other services should make it exceedingly clear that they are not professional mental health providers but an individualized support system where they provide help to their users. Coupling these services with professional counselors and mental health providers can go a long way. Services like 7 Cups can provide a stand-by when users wait to seek help from experts.

Appendix

  • Example Table (ref from Prof. Eisenberg’s revenue model)

revenue_rate.PNG

  • Thanks to Nick Sands and Mitchell Boldin from School of Information, University of Michigan who helped me with the user interviews.
  • This blog post is part of the application process for KPCB Product Fellows
  • This blog post was posted on Indian Standard Time.
  • I will be working with 7 Cups over the next 2.5 months to test their products at the University of Michigan as a Product Management Intern. The research has been done independently and has no association with 7 Cups.

Lessons Learnt

It has been a long time and it has been more than 2 years now I have left college. It has been an enriching and humbling experience and has contributed a lot to my personal growth. Let me share a few of them.

  • Help is always there, we need to ask for it – On numerous occasions, I have taken help and advice from a lot of people around and away from me. They have become valuable friends over a course of time. In case you need some advice, talk to your parents, friends and even strangers (change the context though :P), you may find meaningful insight.
  • Do not hold grudges – We all have good and bad times with people we know. However, as everything in the world is transient, our bad times should not make us hold grudge against them forever. Move On!!!
  • Be an optimist – There are times when one might think there are things that cannot be done. Be an optimist, be patient and keep at it, some day you will get the hang of it.
  • Be your own (wo)man – Everyone finds someone better than themselves at one point or the other and then we start competing with others. What we usually do not realize is that this competition leads to a cheap imitation of our counterpart. We start losing our own identity and then we are no more ourselves.

GSoC Mid terms over, openSUSE Asia Summit to come soon..

Google Summer of Code 2014 reached its mid term last week and I am proud to announce that all of the students from openSUSE have successfully passed their mid term evaluations 🙂

In other news, the openSUSE Project will be holding its first openSUSE Summit in mid-october. It is an exciting news, and anyone who is willing to contribute can do so.

On a personal front, the last 2 weeks have been very laid back and I need to improve on my management skills, lets see.

PS : Writing regular blog posts, is leading me to a place where I dont know what else can I share, maybe a few ideas can help.

GSoC and the past fortnight

Its been almost a fortnight I guess without a blog post, so continuing with the series, I have a couple of updates.

From tomorrow, Google Summer of Code Student Evaluations will start tomorrow on wards, so all the best to all the students who have worked hard over the summer and helped open source organizations grow. An extra applause for the mentors who have really worked hard over the summers and have contributed their personal time to get these students involved. Specifically, from an openSUSE point of view, I hope everyone passes these evaluations.

Apart from these things, I have also hit a couple of realizations over the past fortnight,

  • I have gone worse in programming, something that I intend to improve upon in the next six months
  • I waste a lot of time, I really need to optimize time so that I can work much more efficiently.

And then as news, humblefool one of India’s top programmers died of a car crash. There is an excellent eulogy written by Animesh on quora, I urge you to read it and take inspiration from it.

 

 

SaX3 Localized

Recently, Saurabh Sood suggested me to blog more often, and this an attempt yet again to write more often. Off course, what I may write may or may not be appealing to others, but then its my area 🙂

Anyway, the past few weeks, I have written a bit of code, a bit actually means a teeny weeny bit, but hey, the good news is SaX3 is completely localized / internationalized now and this will be shown in the next openSUSE release.

Offcourse, if you are a translator, you can help me out by translating the files at https://github.com/openSUSE/sax3/tree/master/src/translation and by sending an email with translated files, I will include it in the upcoming repos, I will also try to get it to the openSUSE translation repository, so that lives become easier for all of us.

Other than that, we have a new contributor at openSUSE and who is already writing great articles for the news team, thanks a lot Nenad 🙂
There are plenty of things down the line and I hope I will update the same in the coming weeks,  till then cya people..

openSUSE welcomes its Google Summer of Code Students

openSUSE welcomes Google Summer of Code 2014 participants. Thanks to Google, openSUSE has an excellent number of slots and an equally excellent number of mentors and students for Google Summer of Code 2014. Throughuout the summer, students participanting in this program will code for openSUSE and its sister organizations ownCloud, MATE and Zorp and help them move forward. The best part of GSoC is that most of the code written by students will go upstream and will benefit openSUSE in general also. Along with this, we have an equally good range of projects that will improve
the existing openSUSE architecture.

The list of successful students are :

1. Travel Support Program application –     Karthik Senthil
2. Playlist Functionality for ownCloud Music App –    Volkan
3. ownCloud Calendar Application in angularJS –    Raghu Nayyar
4. openSUSE GSOC ideas: Cool live flash –    Zsolt Peter Basak
5. Open Source Event Manager (OSEM): Refactor user management model –  Stella Rouzi
6. Open Source Event Manager (OSEM): Implemention Organizer Dashboard –    cbruckmayer
7. MATE: Port from deprecated GStreamer 0.10 –    Michal Ratajsky
8. Integrate Snapper Snapshot browsing into openSUSE Desktop tools –  Oguz Kayral
9. Implement an application-level LBaaS driver for Zorp –    Péter Vörös
10. Extend Git-Review to support BitBucket –    xystushi
11. Event Splash page for Visitors In Open Source Event Manager Application. –    Gopesh Tulsyan
12. ePub support in Atril (MATE) –    Avishkar gupta
13. Add Snapshot management API to libvirt Xenlight driver –    David Kiarie
14. Improving the functionality of the extensions system in Caja  – Alexandervdm

In the following weeks I will talk a lot more about these projects and get to know these students well.

Lets brew some code now.

Opa Greeko Style!!!!

What can I say more, The Greeks sure now how to make an event more enjoyable. This conference was definitely something I was not expecting, apart from high technical standards of the conference and also the excellent Geeky People, who knew I guess anything and everything from the world to the parties that the Greeks hosted and the way they managed to skew the timeline to add a bit of surprise to whatever we do plus the sleepless nights and the amazing Greek house along with a random encounter with a bunch of hippies, this trip was nothing but a NIRVANA trip

Thanks a lot again guys for putting the hard work and rounding up an excellent conference.